Compare commits
1 Commits
master
...
af1021ed66
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af1021ed66 |
@@ -29,7 +29,7 @@ parameter
|
|||||||
;
|
;
|
||||||
|
|
||||||
braced_block
|
braced_block
|
||||||
: OBRK statement+ CBRK
|
: OBRK (statement | functionCall SCOL)+ CBRK
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ field_assignment
|
|||||||
;
|
;
|
||||||
|
|
||||||
return_statement
|
return_statement
|
||||||
: RETURN expression SCOL
|
: RETURN expression? SCOL
|
||||||
;
|
;
|
||||||
|
|
||||||
destroy_statement
|
destroy_statement
|
||||||
@@ -116,6 +116,7 @@ type
|
|||||||
| BOOLEAN
|
| BOOLEAN
|
||||||
| FLOAT
|
| FLOAT
|
||||||
| IDENT
|
| IDENT
|
||||||
|
| VOID
|
||||||
;
|
;
|
||||||
|
|
||||||
functionCall
|
functionCall
|
||||||
@@ -181,6 +182,7 @@ DIV: '/';
|
|||||||
BOOLEAN: 'bool';
|
BOOLEAN: 'bool';
|
||||||
INTEGER: 'int';
|
INTEGER: 'int';
|
||||||
FLOAT: 'float';
|
FLOAT: 'float';
|
||||||
|
VOID: 'void';
|
||||||
|
|
||||||
INTEGER_LITERAL
|
INTEGER_LITERAL
|
||||||
: [0-9]+
|
: [0-9]+
|
||||||
|
|||||||
@@ -176,6 +176,11 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
int col = ctx.start.getCharPositionInLine();
|
int col = ctx.start.getCharPositionInLine();
|
||||||
Type declaredType = Type.getByName(ctx.type_annotation().type().getText());
|
Type declaredType = Type.getByName(ctx.type_annotation().type().getText());
|
||||||
|
|
||||||
|
if (declaredType.equals(Type.getVoidType())) {
|
||||||
|
String error = "Type " + declaredType.getName() + " can not be used to declare variables.";
|
||||||
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
|
}
|
||||||
|
|
||||||
if (!declaredType.isPrimitiveType() && this.structs.get(declaredType.getName()) == null) {
|
if (!declaredType.isPrimitiveType() && this.structs.get(declaredType.getName()) == null) {
|
||||||
String error = "Type " + declaredType.getName() + " not defined.";
|
String error = "Type " + declaredType.getName() + " not defined.";
|
||||||
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
@@ -244,10 +249,21 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitReturn_statement(KlangParser.Return_statementContext ctx) {
|
public Node visitReturn_statement(KlangParser.Return_statementContext ctx) {
|
||||||
|
if (currentDeclaredReturnType.equals(Type.getVoidType())) {
|
||||||
|
ReturnStatement result = new ReturnStatement();
|
||||||
|
result.line = ctx.start.getLine();
|
||||||
|
result.type = Type.getVoidType();
|
||||||
|
result.col = ctx.start.getCharPositionInLine();
|
||||||
|
if (ctx.expression() != null) {
|
||||||
|
String error = "Cannot return an expression from a void function.";
|
||||||
|
throw new RuntimeException(Helper.getErrorPrefix(result.line, result.col) + error);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Expression expression = (Expression) this.visit(ctx.expression());
|
Expression expression = (Expression) this.visit(ctx.expression());
|
||||||
ReturnStatement result = new ReturnStatement(expression);
|
ReturnStatement result = new ReturnStatement(expression);
|
||||||
result.type = expression.type;
|
|
||||||
result.line = ctx.start.getLine();
|
result.line = ctx.start.getLine();
|
||||||
|
result.type = expression.type;
|
||||||
result.col = ctx.start.getCharPositionInLine();
|
result.col = ctx.start.getCharPositionInLine();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -721,7 +737,7 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
Type returnType = Type.getByName(ctx.returnType.type().getText());
|
Type returnType = Type.getByName(ctx.returnType.type().getText());
|
||||||
this.currentDeclaredReturnType = returnType;
|
this.currentDeclaredReturnType = returnType;
|
||||||
|
|
||||||
if (!returnType.isPrimitiveType() && this.structs.get(returnType.getName()) == null) {
|
if (!returnType.isPrimitiveType() && this.structs.get(returnType.getName()) == null && !returnType.equals(Type.getVoidType())) {
|
||||||
String error = "Type " + returnType.getName() + " not defined.";
|
String error = "Type " + returnType.getName() + " not defined.";
|
||||||
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
}
|
}
|
||||||
@@ -767,6 +783,11 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
int col = ctx.start.getCharPositionInLine();
|
int col = ctx.start.getCharPositionInLine();
|
||||||
Type type = Type.getByName(ctx.type_annotation().type().getText());
|
Type type = Type.getByName(ctx.type_annotation().type().getText());
|
||||||
|
|
||||||
|
if (type.equals(Type.getVoidType())) {
|
||||||
|
String error = "Type " + type.getName() + " cannot be used to declare a parameter.";
|
||||||
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
|
}
|
||||||
|
|
||||||
if (!type.isPrimitiveType() && this.structs.get(type.getName()) == null) {
|
if (!type.isPrimitiveType() && this.structs.get(type.getName()) == null) {
|
||||||
String error = "Type " + type.getName() + " not defined.";
|
String error = "Type " + type.getName() + " not defined.";
|
||||||
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.HashSet;
|
|||||||
|
|
||||||
import de.hsrm.compiler.Klang.nodes.Node;
|
import de.hsrm.compiler.Klang.nodes.Node;
|
||||||
import de.hsrm.compiler.Klang.nodes.StructDefinition;
|
import de.hsrm.compiler.Klang.nodes.StructDefinition;
|
||||||
|
import de.hsrm.compiler.Klang.types.Type;
|
||||||
import de.hsrm.compiler.Klang.visitors.*;
|
import de.hsrm.compiler.Klang.visitors.*;
|
||||||
import de.hsrm.compiler.Klang.helper.*;
|
import de.hsrm.compiler.Klang.helper.*;
|
||||||
|
|
||||||
@@ -115,7 +116,8 @@ public class Klang {
|
|||||||
PrettyPrintVisitor.ExWriter ex = new PrettyPrintVisitor.ExWriter(w);
|
PrettyPrintVisitor.ExWriter ex = new PrettyPrintVisitor.ExWriter(w);
|
||||||
PrettyPrintVisitor printVisitor = new PrettyPrintVisitor(ex);
|
PrettyPrintVisitor printVisitor = new PrettyPrintVisitor(ex);
|
||||||
root.welcome(printVisitor);
|
root.welcome(printVisitor);
|
||||||
System.out.println(w.toString());
|
generateOutput(out, w.toString());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
@@ -123,7 +125,11 @@ public class Klang {
|
|||||||
System.out.println("\nEvaluating the source code:");
|
System.out.println("\nEvaluating the source code:");
|
||||||
EvalVisitor evalVisitor = new EvalVisitor(structs);
|
EvalVisitor evalVisitor = new EvalVisitor(structs);
|
||||||
Value result = root.welcome(evalVisitor);
|
Value result = root.welcome(evalVisitor);
|
||||||
generateOutput(out, "Result was: " + result.asObject().toString());
|
if (result.type.equals(Type.getVoidType())) {
|
||||||
|
generateOutput(out, "Result was void");
|
||||||
|
} else {
|
||||||
|
generateOutput(out, "Result was: " + result.asObject().toString());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ public class ReturnStatement extends Statement {
|
|||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReturnStatement() {
|
||||||
|
this.expression = null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R> R welcome(Visitor<R> v) {
|
public <R> R welcome(Visitor<R> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ public abstract class Type {
|
|||||||
return NullType.getType();
|
return NullType.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static VoidType getVoidType() {
|
||||||
|
return VoidType.getType();
|
||||||
|
}
|
||||||
|
|
||||||
public static Type getByName(String name) {
|
public static Type getByName(String name) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "bool": return getBooleanType();
|
case "bool": return getBooleanType();
|
||||||
case "int": return getIntegerType();
|
case "int": return getIntegerType();
|
||||||
case "float": return getFloatType();
|
case "float": return getFloatType();
|
||||||
case "null": return getNullType();
|
case "null": return getNullType();
|
||||||
|
case "void": return getVoidType();
|
||||||
default: return new StructType(name);
|
default: return new StructType(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/main/java/de/hsrm/compiler/Klang/types/VoidType.java
Normal file
38
src/main/java/de/hsrm/compiler/Klang/types/VoidType.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package de.hsrm.compiler.Klang.types;
|
||||||
|
|
||||||
|
public class VoidType extends Type {
|
||||||
|
|
||||||
|
private static VoidType instance;
|
||||||
|
|
||||||
|
public static VoidType getType() {
|
||||||
|
if (instance != null) {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
instance = new VoidType();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "void";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type combine(Type that) {
|
||||||
|
if (that.equals(this)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Type missmatch: cannot combine " + this.getName() + " and " + that.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPrimitiveType() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNumericType() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -413,6 +413,9 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value visit(ReturnStatement e) {
|
public Value visit(ReturnStatement e) {
|
||||||
|
if (e.expression == null) {
|
||||||
|
return new Value(null, Type.getVoidType());
|
||||||
|
}
|
||||||
return e.expression.welcome(this);
|
return e.expression.welcome(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -589,7 +589,9 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(ReturnStatement e) {
|
public Void visit(ReturnStatement e) {
|
||||||
e.expression.welcome(this);
|
if (e.expression != null) {
|
||||||
|
e.expression.welcome(this);
|
||||||
|
}
|
||||||
this.ex.write(" movq %rbp, %rsp\n");
|
this.ex.write(" movq %rbp, %rsp\n");
|
||||||
this.ex.write(" popq %rbp\n");
|
this.ex.write(" popq %rbp\n");
|
||||||
this.ex.write(" ret\n");
|
this.ex.write(" ret\n");
|
||||||
|
|||||||
@@ -194,7 +194,9 @@ class GetVars implements Visitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(ReturnStatement e) {
|
public Void visit(ReturnStatement e) {
|
||||||
e.expression.welcome(this);
|
if (e.expression != null) {
|
||||||
|
e.expression.welcome(this);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -304,8 +304,11 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(ReturnStatement e) {
|
public Void visit(ReturnStatement e) {
|
||||||
ex.write("return ");
|
ex.write("return");
|
||||||
e.expression.welcome(this);
|
if (e.expression != null) {
|
||||||
|
ex.write(" ");
|
||||||
|
e.expression.welcome(this);
|
||||||
|
}
|
||||||
ex.write(";");
|
ex.write(";");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user