|
|
@ -132,7 +132,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
public Void visitCallCommand(CallCommand ast, Void arg) { |
|
|
|
public Void visitCallCommand(CallCommand ast, Void arg) { |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
|
|
|
|
|
|
|
|
if (binding instanceof ProcedureDeclaration procedure) { |
|
|
|
if (binding instanceof ProcedureDeclaration) { |
|
|
|
|
|
|
|
ProcedureDeclaration procedure = (ProcedureDeclaration)binding; |
|
|
|
ast.APS.visit(this, procedure.getFormals()); |
|
|
|
ast.APS.visit(this, procedure.getFormals()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier"); |
|
|
|
reportUndeclaredOrError(binding, ast.I, "\"%\" is not a procedure identifier"); |
|
|
@ -203,7 +204,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
var e2Type = ast.E2.visit(this); |
|
|
|
var e2Type = ast.E2.visit(this); |
|
|
|
var binding = ast.O.visit(this); |
|
|
|
var binding = ast.O.visit(this); |
|
|
|
|
|
|
|
|
|
|
|
if (binding instanceof BinaryOperatorDeclaration bbinding) { |
|
|
|
if (binding instanceof BinaryOperatorDeclaration) { |
|
|
|
|
|
|
|
BinaryOperatorDeclaration bbinding = (BinaryOperatorDeclaration)binding; |
|
|
|
if (bbinding.ARG1.equals(StdEnvironment.anyType)) { |
|
|
|
if (bbinding.ARG1.equals(StdEnvironment.anyType)) { |
|
|
|
// this operator must be "=" or "\="
|
|
|
|
// this operator must be "=" or "\="
|
|
|
|
checkAndReportError(e1Type.equals(e2Type), "incompatible argument types for \"%\"", ast.O, ast); |
|
|
|
checkAndReportError(e1Type.equals(e2Type), "incompatible argument types for \"%\"", ast.O, ast); |
|
|
@ -222,7 +224,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
public TypeDenoter visitCallExpression(CallExpression ast, Void arg) { |
|
|
|
public TypeDenoter visitCallExpression(CallExpression ast, Void arg) { |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
|
|
|
|
|
|
|
|
if (binding instanceof FunctionDeclaration function) { |
|
|
|
if (binding instanceof FunctionDeclaration) { |
|
|
|
|
|
|
|
FunctionDeclaration function = (FunctionDeclaration)binding; |
|
|
|
ast.APS.visit(this, function.getFormals()); |
|
|
|
ast.APS.visit(this, function.getFormals()); |
|
|
|
return ast.type = function.getType(); |
|
|
|
return ast.type = function.getType(); |
|
|
|
} |
|
|
|
} |
|
|
@ -277,7 +280,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
var eType = ast.E.visit(this); |
|
|
|
var eType = ast.E.visit(this); |
|
|
|
var binding = ast.O.visit(this); |
|
|
|
var binding = ast.O.visit(this); |
|
|
|
|
|
|
|
|
|
|
|
if (binding instanceof UnaryOperatorDeclaration ubinding) { |
|
|
|
if (binding instanceof UnaryOperatorDeclaration) { |
|
|
|
|
|
|
|
UnaryOperatorDeclaration ubinding = (UnaryOperatorDeclaration)binding; |
|
|
|
checkAndReportError(eType.equals(ubinding.ARG), "wrong argument type for \"%\"", ast.O); |
|
|
|
checkAndReportError(eType.equals(ubinding.ARG), "wrong argument type for \"%\"", ast.O); |
|
|
|
return ast.type = ubinding.RES; |
|
|
|
return ast.type = ubinding.RES; |
|
|
|
} |
|
|
|
} |
|
|
@ -472,8 +476,9 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Void visitConstActualParameter(ConstActualParameter ast, FormalParameter arg) { |
|
|
|
public Void visitConstActualParameter(ConstActualParameter ast, FormalParameter arg) { |
|
|
|
var eType = ast.E.visit(this); |
|
|
|
var eType = ast.E.visit(this); |
|
|
|
if (arg instanceof ConstFormalParameter param) { |
|
|
|
if (arg instanceof ConstFormalParameter) { |
|
|
|
checkAndReportError(eType.equals(param.T), "wrong type for const actual parameter", ast.E); |
|
|
|
ConstFormalParameter param = (ConstFormalParameter)arg; |
|
|
|
|
|
|
|
checkAndReportError(eType.equals(((ConstFormalParameter)arg).T), "wrong type for const actual parameter", ast.E); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
reportError("const actual parameter not expected here", ast); |
|
|
|
reportError("const actual parameter not expected here", ast); |
|
|
|
} |
|
|
|
} |
|
|
@ -483,10 +488,12 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Void visitFuncActualParameter(FuncActualParameter ast, FormalParameter arg) { |
|
|
|
public Void visitFuncActualParameter(FuncActualParameter ast, FormalParameter arg) { |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
if (binding instanceof FunctionDeclaration function) { |
|
|
|
if (binding instanceof FunctionDeclaration) { |
|
|
|
|
|
|
|
FunctionDeclaration function = (FunctionDeclaration)binding; |
|
|
|
var formals = function.getFormals(); |
|
|
|
var formals = function.getFormals(); |
|
|
|
var functionType = function.getType(); |
|
|
|
var functionType = function.getType(); |
|
|
|
if (arg instanceof FuncFormalParameter param) { |
|
|
|
if (arg instanceof FuncFormalParameter) { |
|
|
|
|
|
|
|
FuncFormalParameter param = (FuncFormalParameter)arg; |
|
|
|
if (!formals.equals(param.getFormals())) { |
|
|
|
if (!formals.equals(param.getFormals())) { |
|
|
|
reportError("wrong signature for function \"%\"", ast.I); |
|
|
|
reportError("wrong signature for function \"%\"", ast.I); |
|
|
|
} else if (!functionType.equals(param.T)) { |
|
|
|
} else if (!functionType.equals(param.T)) { |
|
|
@ -504,9 +511,11 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Void visitProcActualParameter(ProcActualParameter ast, FormalParameter arg) { |
|
|
|
public Void visitProcActualParameter(ProcActualParameter ast, FormalParameter arg) { |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
if (binding instanceof ProcedureDeclaration procedure) { |
|
|
|
if (binding instanceof ProcedureDeclaration) { |
|
|
|
|
|
|
|
ProcedureDeclaration procedure = (ProcedureDeclaration)binding; |
|
|
|
var formals = procedure.getFormals(); |
|
|
|
var formals = procedure.getFormals(); |
|
|
|
if (arg instanceof ProcFormalParameter param) { |
|
|
|
if (arg instanceof ProcFormalParameter) { |
|
|
|
|
|
|
|
ProcFormalParameter param = (ProcFormalParameter)arg; |
|
|
|
checkAndReportError(formals.equals(param.getFormals()), "wrong signature for procedure \"%\"", ast.I); |
|
|
|
checkAndReportError(formals.equals(param.getFormals()), "wrong signature for procedure \"%\"", ast.I); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
reportError("proc actual parameter not expected here", ast); |
|
|
|
reportError("proc actual parameter not expected here", ast); |
|
|
@ -522,7 +531,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
var vType = ast.V.visit(this); |
|
|
|
var vType = ast.V.visit(this); |
|
|
|
if (!ast.V.variable) { |
|
|
|
if (!ast.V.variable) { |
|
|
|
reportError("actual parameter is not a variable", ast.V); |
|
|
|
reportError("actual parameter is not a variable", ast.V); |
|
|
|
} else if (arg instanceof VarFormalParameter parameter) { |
|
|
|
} else if (arg instanceof VarFormalParameter) { |
|
|
|
|
|
|
|
VarFormalParameter parameter = (VarFormalParameter)arg; |
|
|
|
checkAndReportError(vType.equals(parameter.T), "wrong type for var actual parameter", ast.V); |
|
|
|
checkAndReportError(vType.equals(parameter.T), "wrong type for var actual parameter", ast.V); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
reportError("var actual parameter not expected here", ast.V); |
|
|
|
reportError("var actual parameter not expected here", ast.V); |
|
|
@ -538,7 +548,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Void visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, FormalParameterSequence arg) { |
|
|
|
public Void visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, FormalParameterSequence arg) { |
|
|
|
if (arg instanceof MultipleFormalParameterSequence formals) { |
|
|
|
if (arg instanceof MultipleFormalParameterSequence) { |
|
|
|
|
|
|
|
MultipleFormalParameterSequence formals = (MultipleFormalParameterSequence)arg; |
|
|
|
ast.AP.visit(this, formals.FP); |
|
|
|
ast.AP.visit(this, formals.FP); |
|
|
|
ast.APS.visit(this, formals.FPS); |
|
|
|
ast.APS.visit(this, formals.FPS); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -549,7 +560,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Void visitSingleActualParameterSequence(SingleActualParameterSequence ast, FormalParameterSequence arg) { |
|
|
|
public Void visitSingleActualParameterSequence(SingleActualParameterSequence ast, FormalParameterSequence arg) { |
|
|
|
if (arg instanceof SingleFormalParameterSequence formal) { |
|
|
|
if (arg instanceof SingleFormalParameterSequence) { |
|
|
|
|
|
|
|
SingleFormalParameterSequence formal = (SingleFormalParameterSequence)arg; |
|
|
|
ast.AP.visit(this, formal.FP); |
|
|
|
ast.AP.visit(this, formal.FP); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
reportError("incorrect number of actual parameters", ast); |
|
|
|
reportError("incorrect number of actual parameters", ast); |
|
|
@ -592,7 +604,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public TypeDenoter visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) { |
|
|
|
public TypeDenoter visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) { |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
if (binding instanceof TypeDeclaration decl) { |
|
|
|
if (binding instanceof TypeDeclaration) { |
|
|
|
|
|
|
|
TypeDeclaration decl = (TypeDeclaration)binding; |
|
|
|
return decl.T; |
|
|
|
return decl.T; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -678,7 +691,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
public TypeDenoter visitDotVname(DotVname ast, Void arg) { |
|
|
|
public TypeDenoter visitDotVname(DotVname ast, Void arg) { |
|
|
|
ast.type = null; |
|
|
|
ast.type = null; |
|
|
|
var vType = ast.V.visit(this); |
|
|
|
var vType = ast.V.visit(this); |
|
|
|
if (vType instanceof RecordTypeDenoter record) { |
|
|
|
if (vType instanceof RecordTypeDenoter) { |
|
|
|
|
|
|
|
RecordTypeDenoter record = (RecordTypeDenoter)vType; |
|
|
|
ast.type = checkFieldIdentifier(record.FT, ast.I); |
|
|
|
ast.type = checkFieldIdentifier(record.FT, ast.I); |
|
|
|
checkAndReportError(!ast.type.equals(StdEnvironment.errorType), "no field \"%\" in this record type", |
|
|
|
checkAndReportError(!ast.type.equals(StdEnvironment.errorType), "no field \"%\" in this record type", |
|
|
|
ast.I); |
|
|
|
ast.I); |
|
|
@ -694,9 +708,11 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
ast.type = StdEnvironment.errorType; |
|
|
|
ast.type = StdEnvironment.errorType; |
|
|
|
|
|
|
|
|
|
|
|
var binding = ast.I.visit(this); |
|
|
|
var binding = ast.I.visit(this); |
|
|
|
if (binding instanceof ConstantDeclaration constant) { |
|
|
|
if (binding instanceof ConstantDeclaration) { |
|
|
|
|
|
|
|
ConstantDeclaration constant = (ConstantDeclaration)binding; |
|
|
|
return ast.type = constant.getType(); |
|
|
|
return ast.type = constant.getType(); |
|
|
|
} else if (binding instanceof VariableDeclaration variable) { |
|
|
|
} else if (binding instanceof VariableDeclaration) { |
|
|
|
|
|
|
|
VariableDeclaration variable = (VariableDeclaration)binding; |
|
|
|
return ast.type = variable.getType(); |
|
|
|
return ast.type = variable.getType(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -711,7 +727,8 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
|
|
|
|
|
|
|
|
var eType = ast.E.visit(this); |
|
|
|
var eType = ast.E.visit(this); |
|
|
|
if (vType != StdEnvironment.errorType) { |
|
|
|
if (vType != StdEnvironment.errorType) { |
|
|
|
if (vType instanceof ArrayTypeDenoter arrayType) { |
|
|
|
if (vType instanceof ArrayTypeDenoter) { |
|
|
|
|
|
|
|
ArrayTypeDenoter arrayType = (ArrayTypeDenoter)vType; |
|
|
|
checkAndReportError(eType.equals(StdEnvironment.integerType), "Integer expression expected here", |
|
|
|
checkAndReportError(eType.equals(StdEnvironment.integerType), "Integer expression expected here", |
|
|
|
ast.E); |
|
|
|
ast.E); |
|
|
|
ast.type = arrayType.T; |
|
|
|
ast.type = arrayType.T; |
|
|
@ -796,14 +813,16 @@ public final class Checker implements ActualParameterVisitor<FormalParameter, Vo |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static TypeDenoter checkFieldIdentifier(FieldTypeDenoter ast, Identifier I) { |
|
|
|
private static TypeDenoter checkFieldIdentifier(FieldTypeDenoter ast, Identifier I) { |
|
|
|
if (ast instanceof MultipleFieldTypeDenoter ft) { |
|
|
|
if (ast instanceof MultipleFieldTypeDenoter) { |
|
|
|
|
|
|
|
MultipleFieldTypeDenoter ft = (MultipleFieldTypeDenoter)ast; |
|
|
|
if (ft.I.spelling.compareTo(I.spelling) == 0) { |
|
|
|
if (ft.I.spelling.compareTo(I.spelling) == 0) { |
|
|
|
I.decl = ast; |
|
|
|
I.decl = ast; |
|
|
|
return ft.T; |
|
|
|
return ft.T; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
return checkFieldIdentifier(ft.FT, I); |
|
|
|
return checkFieldIdentifier(ft.FT, I); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (ast instanceof SingleFieldTypeDenoter ft) { |
|
|
|
} else if (ast instanceof SingleFieldTypeDenoter) { |
|
|
|
|
|
|
|
SingleFieldTypeDenoter ft = (SingleFieldTypeDenoter)ast; |
|
|
|
if (ft.I.spelling.compareTo(I.spelling) == 0) { |
|
|
|
if (ft.I.spelling.compareTo(I.spelling) == 0) { |
|
|
|
I.decl = ast; |
|
|
|
I.decl = ast; |
|
|
|
return ft.T; |
|
|
|
return ft.T; |
|
|
|