public override Type visitVarDef(VariableDeclaration varDef, Environment env) { string name = varDef.name; Type declaredType = scan(varDef.type, env); Expression init = varDef.init; VarSymbol varSymbol = new VarSymbol(Kind.LOCAL, name, declaredType, env.enclFunc); varDef.symbol = varSymbol; if (init != null) { Type initType = analyzeExpr(init, env); if (!typings.isAssignableFrom(declaredType, initType)) { log.error(varDef.Pos, messages.varInitTypeMismatch, name, initType, declaredType); } } if (check.checkUniqueLocalVar(varDef.Pos, varSymbol, (WritableScope)env.scope)) { ((WritableScope)env.scope).enter(varSymbol); } // probably unused return(declaredType); }
public override void GenerateLValue(AsmCode asmCode, SymTable symTable) { var t = symTable.LookUpLevel(Value.ToString()); VarSymbol v = (VarSymbol)t?.Item1; int level = t.Value.Item2; asmCode.Add(AsmCmd.Cmd.Mov, AsmReg.Reg.Eax, AsmReg.Reg.Ebp); while (level-- > 0) { asmCode.Add( AsmCmd.Cmd.Mov, AsmReg.Reg.Eax, new AsmOffset(-8, 4, AsmReg.Reg.Eax)); } asmCode.Add( AsmCmd.Cmd.Lea, AsmReg.Reg.Eax, new AsmOffset(v.Offset, 0, AsmReg.Reg.Eax)); if (v is ParameterSymbol ps && ps.ParameterModifier != ParameterModifier.Value) { asmCode.Add( AsmCmd.Cmd.Mov, AsmReg.Reg.Eax, new AsmOffset(0, 4, AsmReg.Reg.Eax)); } asmCode.Add(AsmCmd.Cmd.Push, AsmReg.Reg.Eax); }
private void declareSymbol(Var node, Type t) { ISymbol typeSymbol = scope.find(t.name); string varName = node.name; VarSymbol varSymbol = new VarSymbol(varName, typeSymbol.name); scope.define(varSymbol as ISymbol); }
public bool checkUniqueLocalVar(DiagnosticPosition pos, VarSymbol varSymbol, WritableScope scope) { if (scope.getSymbolsByName(varSymbol.name, s => (s.kind & Kind.VAR) != 0).Any()) { log.error(pos, messages.duplicateVar, varSymbol.name); return(false); } return(true); }
public bool checkUniqueParam(DiagnosticPosition pos, VarSymbol param, Scope scope) { if (scope.getSymbolsByName(param.name, LookupKind.NON_RECURSIVE).Any()) { log.error(pos, messages.duplicateParamName, param.name, scope.owner.name); return(false); } return(true); }
public override Exit visitIdent(Identifier ident, Environment env) { VarSymbol varSym = ident.symbol; if (varSym.kind == Kind.LOCAL && !env.isAssigned(varSym)) { log.error(ident.Pos, messages.unassignedVariable, ident.name); } return(0); }
private void enterParameter(VariableDeclaration varDef, WritableScope scope) { Type varType = (Type)scan(varDef.type, scope); FuncSymbol func = (FuncSymbol)scope.owner; VarSymbol varSym = new VarSymbol(Kind.PARAM, varDef.name, varType, func); varDef.symbol = varSym; func.parameters.Add(varSym); if (check.checkUniqueParam(varDef.Pos, varSym, scope)) { scope.enter(varSym); } }
public override string Gen() { if (this.IsConstant()) { return(this.Val().Gen()); } string code = string.Empty; if (indexer == null) { code += value?.Gen() ?? string.Empty; code += expr?.Gen() ?? string.Empty; code += func?.Gen() ?? string.Empty; } else { VarSymbol arr = SymbolTable.FindVar((value as IdNode).name); code += indexer.Gen(); code += $"mov\trbx, [rbp{(-arr.offsetInFun>0?"+":"")}{-arr.offsetInFun}]\n"; code += $"lea\t{CodeGenUtils.CurrentStackTop64}, [rbx+{CodeGenUtils.CurrentStackTop64}*{arr.eleSize}]\n"; switch (arr.eleSize) { case 1: code += $"movsx\t{CodeGenUtils.CurrentStackTop64}, byte [{CodeGenUtils.CurrentStackTop64}]\n"; break; case 4: code += $"mov\t{CodeGenUtils.CurrentStackTop32}, [{CodeGenUtils.CurrentStackTop64}]\n"; if (CodeGenUtils.CurrentStackTop32 == "eax") { code += "cdqe\n"; } else { code += $"xchg\trax, {CodeGenUtils.CurrentStackTop64}\n"; code += "cdqe\n"; code += $"xchg\trax, {CodeGenUtils.CurrentStackTop64}\n"; } break; case 8: code += $"mov\t{CodeGenUtils.CurrentStackTop64}, [{CodeGenUtils.CurrentStackTop64}]\n"; break; } } return(code); }
public bool isAssigned(VarSymbol varSym) { bool contains = inits.Contains(varSym); if (contains) { return(true); } if (parent != null) { return(parent.isAssigned(varSym)); } return(false); }
public override Exit visitAssign(AssignNode expr, Environment env) { analyzeExpr(expr.right, env); if (expr.left is Identifier id) { VarSymbol varSym = id.symbol; if (varSym.kind == Kind.LOCAL) { env.assigned(varSym); } } else { analyzeExpr(expr.left, env); } return(0); }
public override Type visitSelect(Select select, Environment env) { Type leftType = analyzeExpr(select.selectBase, env); if (leftType.IsError) { select.symbol = symtab.errorVarSymbol; return(symtab.errorType); } if (leftType.IsPrimitive) { log.error(select.Pos, messages.selectOnPrimitive); select.symbol = symtab.errorVarSymbol; return(symtab.errorType); } if (leftType.IsArray) { if (select.name != "length") { log.error(select.Pos, "Arrays only have a \"length\" field"); return(symtab.errorType); } select.symbol = symtab.arrayLengthField; select.type = symtab.arrayLengthField.type; return(select.type); } StructSymbol ssym = ((StructType)leftType).symbol; VarSymbol field = (VarSymbol)ssym.membersScope.findFirst(select.name); if (field == null) { log.error(select.Pos, messages.unknownField, select.name, ssym.name); select.symbol = symtab.errorVarSymbol; return(symtab.errorType); } select.symbol = field; select.type = field.type; return(field.type); }
/** * INFO: This is for fields. Another non-visitor routine is for function parameters. */ public override object visitVarDef(VariableDeclaration varDef, WritableScope compoundScope) { WritableScope membersScope = ((StructSymbol)compoundScope.owner).membersScope; // TODO: Should be NON_RECURSIVE Symbol sym = membersScope.findFirst(varDef.name); if (sym != null) { log.error(varDef.Pos, messages.duplicateMember, varDef.name, membersScope.owner.name); } else { VarSymbol var = new VarSymbol(Kind.FIELD, varDef.name, (Type)scan(varDef.type, compoundScope), membersScope.owner); membersScope.enter(var); varDef.symbol = var; } return(null); }
public void visit(ProcDecl procDecl) { if (scope.scopeLevel == Dictionary.MAX_NEST_LEVEL) { throw new Exception(Dictionary.max_nest_level_exc); } ProcedureSymbol procSym = new ProcedureSymbol(procDecl.name); scope.define(procSym); scope = new ScopeSymbolTable(scope.scopeLevel + 1, scope); foreach (Param param in procDecl.parameters) { VarSymbol paramSymbol = createParamSymbol(param); scope.define(paramSymbol); procSym.parameters.Add(paramSymbol); } foreach (IAST child in procDecl.children) { child.accept(this); } scope = scope.globalScope; }
private Type analyzeInvocation(FuncInvocation invocation, FuncSymbol fsym, Environment env) { IList <Expression> args = invocation.args; // check argument count IList <VarSymbol> paramSyms = fsym.parameters; if (fsym.isVararg ? args.Count < paramSyms.Count : args.Count != paramSyms.Count) { log.error(invocation.Pos, messages.wrongNumberOfArgs, fsym.name, paramSyms.Count, args.Count); } // check argument types int count = Math.Min(args.Count, paramSyms.Count); for (int i = 0; i < count; i++) { VarSymbol paramSym = paramSyms[i]; Type argType = analyzeExpr(args[i], env); // we don't consider implicit numeric conversions for now if (!typings.isAssignableFrom(paramSym.type, argType)) { log.error(invocation.Pos, messages.paramTypeMismatch, fsym.name); } } for (int i = count; i < args.Count; ++i) { analyzeExpr(args[i], env); } fsym.isInvoked = true; invocation.funcSym = fsym; invocation.type = fsym.type.ReturnType; return(fsym.type.ReturnType); }
public void assigned(VarSymbol varSym) { inits.Add(varSym); }
public override VarType Type() { VarSymbol item = SymbolTable.FindVar(name); return(item?.type ?? VarType.TYPE_ERROR); }