Remove FunctionInformation and replace it with FunctionDefinition.

This commit is contained in:
2023-03-15 16:19:42 +01:00
parent 7af815042b
commit 6e4431652c
5 changed files with 39 additions and 59 deletions

View File

@@ -1,9 +1,5 @@
package de.hsrm.compiler.Klang; package de.hsrm.compiler.Klang;
import java.util.Map;
import java.util.HashMap;
import de.hsrm.compiler.Klang.helper.FunctionInformation;
import de.hsrm.compiler.Klang.helper.Helper; import de.hsrm.compiler.Klang.helper.Helper;
import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.*;
import de.hsrm.compiler.Klang.nodes.expressions.*; import de.hsrm.compiler.Klang.nodes.expressions.*;
@@ -13,9 +9,12 @@ import de.hsrm.compiler.Klang.nodes.loops.WhileLoop;
import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.types.Type; import de.hsrm.compiler.Klang.types.Type;
import java.util.HashMap;
import java.util.Map;
public class ContextAnalysis extends KlangBaseVisitor<Node> { public class ContextAnalysis extends KlangBaseVisitor<Node> {
Map<String, VariableDeclaration> vars = new HashMap<>(); Map<String, VariableDeclaration> vars = new HashMap<>();
Map<String, FunctionInformation> functionDefs; Map<String, FunctionDefinition> functionDefs;
Map<String, StructDefinition> structDefs; Map<String, StructDefinition> structDefs;
Map<String, EnumDefinition> enumDefs; Map<String, EnumDefinition> enumDefs;
Type currentDeclaredReturnType; Type currentDeclaredReturnType;
@@ -29,7 +28,7 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
} }
public ContextAnalysis( public ContextAnalysis(
Map<String, FunctionInformation> functionDefs, Map<String, FunctionDefinition> functionDefs,
Map<String, StructDefinition> structDefs, Map<String, StructDefinition> structDefs,
Map<String, EnumDefinition> enumDefs Map<String, EnumDefinition> enumDefs
) { ) {
@@ -801,15 +800,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
FunctionInformation func = this.functionDefs.get(name); var functionDef = this.functionDefs.get(name);
if (func == null) { if (functionDef == null) {
String error = "Function with name \"" + name + "\" not defined."; String error = "Function with name \"" + name + "\" not defined.";
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
} }
// Make sure the number of arguments matches the number of parameters // Make sure the number of arguments matches the number of parameters
int argCount = ctx.functionCall().arguments().expression().size(); int argCount = ctx.functionCall().arguments().expression().size();
int paramCount = func.parameters.size(); int paramCount = functionDef.parameters.length;
if (argCount != paramCount) { if (argCount != paramCount) {
String error = "Function \"" + name + "\" expects " + paramCount + " parameters, but got " + argCount + "."; String error = "Function \"" + name + "\" expects " + paramCount + " parameters, but got " + argCount + ".";
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
@@ -819,14 +818,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
Expression[] args = new Expression[argCount]; Expression[] args = new Expression[argCount];
for (int i = 0; i < argCount; i++) { for (int i = 0; i < argCount; i++) {
Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i)); Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i));
if (!expression.type.equals(func.signature[i])) { if (!expression.type.equals(functionDef.parameters[i].type)) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " Expected " + func.signature[i].getName() + " but got: " + expression.type.getName()); throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " Expected " + functionDef.parameters[i].type.getName() + " but got: " + expression.type.getName());
} }
args[i] = expression; args[i] = expression;
} }
FunctionCall result = new FunctionCall(name, args); FunctionCall result = new FunctionCall(name, args);
result.type = func.returnType; result.type = functionDef.type;
result.line = line; result.line = line;
result.col = col; result.col = col;
return result; return result;

View File

@@ -1,19 +1,18 @@
package de.hsrm.compiler.Klang; package de.hsrm.compiler.Klang;
import de.hsrm.compiler.Klang.helper.FunctionInformation;
import de.hsrm.compiler.Klang.helper.Helper; import de.hsrm.compiler.Klang.helper.Helper;
import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.*;
import de.hsrm.compiler.Klang.types.EnumType; import de.hsrm.compiler.Klang.types.EnumType;
import de.hsrm.compiler.Klang.types.StructType; import de.hsrm.compiler.Klang.types.StructType;
import de.hsrm.compiler.Klang.types.Type; import de.hsrm.compiler.Klang.types.Type;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
public class GetDefinitions extends KlangBaseVisitor<Node> { public class GetDefinitions extends KlangBaseVisitor<Node> {
private final Map<String, FunctionInformation> functionDefs; private final Map<String, FunctionDefinition> functionDefs;
private final Map<String, StructDefinition> structDefs; private final Map<String, StructDefinition> structDefs;
private final Map<String, EnumDefinition> enumDefs; private final Map<String, EnumDefinition> enumDefs;
@@ -22,7 +21,7 @@ public class GetDefinitions extends KlangBaseVisitor<Node> {
private Set<String> enumNames; private Set<String> enumNames;
public GetDefinitions( public GetDefinitions(
Map<String, FunctionInformation> functionDefs, Map<String, FunctionDefinition> functionDefs,
Map<String, StructDefinition> structDefs, Map<String, StructDefinition> structDefs,
Map<String, EnumDefinition> enumDefs Map<String, EnumDefinition> enumDefs
) { ) {
@@ -138,8 +137,7 @@ public class GetDefinitions extends KlangBaseVisitor<Node> {
public Node visitStructDef(KlangParser.StructDefContext ctx) { public Node visitStructDef(KlangParser.StructDefContext ctx) {
var structName = ctx.structName.getText(); var structName = ctx.structName.getText();
var structFieldCount = ctx.structField().size(); var structFieldCount = ctx.structField().size();
var structFields = new StructField[structFieldCount]; var structFields = new HashMap<String, StructField>();
var structFieldNames = new HashSet<String>();
var line = ctx.start.getLine(); var line = ctx.start.getLine();
var col = ctx.start.getCharPositionInLine(); var col = ctx.start.getCharPositionInLine();
@@ -152,25 +150,23 @@ public class GetDefinitions extends KlangBaseVisitor<Node> {
for (int i = 0; i < structFieldCount; i++) { for (int i = 0; i < structFieldCount; i++) {
var currentStructField = ctx.structField(i); var currentStructField = ctx.structField(i);
var structFieldName = currentStructField.IDENT().getText(); var structFieldName = currentStructField.IDENT().getText();
var structFieldTypeName = currentStructField.type_annotation().type().getText();
var structFieldLine = currentStructField.start.getLine(); var structFieldLine = currentStructField.start.getLine();
var structFieldCol = currentStructField.start.getCharPositionInLine(); var structFieldCol = currentStructField.start.getCharPositionInLine();
if (structFieldNames.contains(structFieldName)) { if (structFields.containsKey(structFieldName)) {
var error = "Duplicate struct field " + structFieldName + " in struct " + structName + "."; var error = "Duplicate struct field " + structFieldName + " in struct " + structName + ".";
throw new RuntimeException(Helper.getErrorPrefix(structFieldLine, structFieldCol) + error); throw new RuntimeException(Helper.getErrorPrefix(structFieldLine, structFieldCol) + error);
} }
var structField = new StructField(structFieldName); var structField = new StructField(structFieldName);
structField.type = Type.getByName(structFieldTypeName); structField.type = Type.getByName(currentStructField.type_annotation().type().getText());
structField.line = structFieldLine; structField.line = structFieldLine;
structField.col = structFieldCol; structField.col = structFieldCol;
structFieldNames.add(structFieldName); structFields.put(structFieldName, structField);
structFields[i] = structField;
} }
var structDef = new StructDefinition(structName, structFields); var structDef = new StructDefinition(structName, structFields.values().toArray(new StructField[0]));
structDef.line = line; structDef.line = line;
structDef.col = col; structDef.col = col;
structDef.type = new StructType(structName); structDef.type = new StructType(structName);
@@ -182,37 +178,41 @@ public class GetDefinitions extends KlangBaseVisitor<Node> {
@Override @Override
public Node visitFunctionDef(KlangParser.FunctionDefContext ctx) { public Node visitFunctionDef(KlangParser.FunctionDefContext ctx) {
var funcName = ctx.funcName.getText(); var funcName = ctx.funcName.getText();
var returnType = Type.getByName(ctx.returnType.getText());
var parameters = new TreeMap<String, Type>();
var paramCount = ctx.params.parameter().size(); var paramCount = ctx.params.parameter().size();
var signature = new Type[paramCount]; var parameters = new HashMap<String, Parameter>();
var line = ctx.start.getLine();
var col = ctx.start.getCharPositionInLine();
// Check that there isn't a struct or enum with the same name // Check that there isn't a struct or enum with the same name
if (structNames.contains(funcName) || enumNames.contains(funcName)) { if (structNames.contains(funcName) || enumNames.contains(funcName)) {
var line = ctx.start.getLine();
var col = ctx.start.getCharPositionInLine();
var error = "Duplicate use of name " + funcName + "."; var error = "Duplicate use of name " + funcName + ".";
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
} }
for (int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
var currentParam = ctx.params.parameter(i); var currentParam = ctx.params.parameter(i);
var paramType = Type.getByName(currentParam.type_annotation().type().getText());
var paramName = currentParam.IDENT().getText(); var paramName = currentParam.IDENT().getText();
var paramLine = currentParam.start.getLine();
var paramCol = currentParam.start.getCharPositionInLine();
if (parameters.containsKey(paramName)) { if (parameters.containsKey(paramName)) {
var paramLine = currentParam.start.getLine();
var paramCol = currentParam.start.getCharPositionInLine();
var error = "Duplicate parameter name " + paramName + " in function " + funcName + "."; var error = "Duplicate parameter name " + paramName + " in function " + funcName + ".";
throw new RuntimeException(Helper.getErrorPrefix(paramLine, paramCol) + error); throw new RuntimeException(Helper.getErrorPrefix(paramLine, paramCol) + error);
} }
parameters.put(paramName, paramType); var parameter = new Parameter(paramName);
signature[i] = paramType; parameter.type = Type.getByName(currentParam.type_annotation().type().getText());
parameter.line = paramLine;
parameter.col = paramCol;
parameters.put(paramName, parameter);
} }
var information = new FunctionInformation(funcName, returnType, parameters, signature); var functionDef = new FunctionDefinition(funcName, parameters.values().toArray(new Parameter[0]), null);
functionDefs.put(funcName, information); functionDef.type = Type.getByName(ctx.returnType.getText());
functionDef.line = line;
functionDef.col = col;
functionDefs.put(funcName, functionDef);
return null; return null;
} }
} }

View File

@@ -1,7 +1,7 @@
package de.hsrm.compiler.Klang; package de.hsrm.compiler.Klang;
import de.hsrm.compiler.Klang.helper.FunctionInformation;
import de.hsrm.compiler.Klang.nodes.EnumDefinition; import de.hsrm.compiler.Klang.nodes.EnumDefinition;
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
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.visitors.EvalVisitor; import de.hsrm.compiler.Klang.visitors.EvalVisitor;
@@ -90,7 +90,7 @@ public class Klang {
// Context Analysis and DAST generation // Context Analysis and DAST generation
Node root; Node root;
var functionDefs = new HashMap<String, FunctionInformation>(); var functionDefs = new HashMap<String, FunctionDefinition>();
var structDefs = new HashMap<String, StructDefinition>(); var structDefs = new HashMap<String, StructDefinition>();
var enumDefs = new HashMap<String, EnumDefinition>(); var enumDefs = new HashMap<String, EnumDefinition>();
try { try {

View File

@@ -1,19 +0,0 @@
package de.hsrm.compiler.Klang.helper;
import java.util.Map;
import de.hsrm.compiler.Klang.types.Type;
public class FunctionInformation {
public String name;
public Type returnType;
public Map<String, Type> parameters;
public Type[] signature;
public FunctionInformation(String name, Type returnType, Map<String,Type> parameters, Type[] signature) {
this.name = name;
this.returnType = returnType;
this.parameters = parameters;
this.signature = signature;
}
}

View File

@@ -16,8 +16,8 @@ public class Helper {
return parser.parse(); return parser.parse();
} }
public static Map<String, FunctionInformation> getFuncs(ParseTree tree) { public static Map<String, FunctionDefinition> getFuncs(ParseTree tree) {
var functionDefinitions = new HashMap<String, FunctionInformation>(); var functionDefinitions = new HashMap<String, FunctionDefinition>();
new GetDefinitions(functionDefinitions, new HashMap<>(), new HashMap<>()).visit(tree); new GetDefinitions(functionDefinitions, new HashMap<>(), new HashMap<>()).visit(tree);
return functionDefinitions; return functionDefinitions;
} }