private void emitStatement(Node stmt, bool is_last = false) { if (stmt is DeclareVar decl) { localSymbols[decl.var.lexeme] = il.DeclareLocal(ToType(decl.type)); if (!(decl.expr is null)) { AssignVar assign = new AssignVar(decl.var, decl.expr); emitExpr(assign); } } else if (stmt is ReturnValue ret) { emitExpr(ret.value); if (!is_last) { il.Emit(OpCodes.Ret); } } else { emitExpr(stmt); } }
private Node parseAssign() { Node left = parseTerm(); while (match(TType.EQUALS)) { if (left is Variable var) { left = new AssignVar(var.Name, parseTerm()); } else if (left is IndexArray idxarr) { left = new SetInArray(idxarr.value, idxarr.idx, parseTerm()); } else { throw new Exception("Invalid assignment target (Expected variable or array index)"); } } return(left); }
private void emitDecl(CodeBlock decls) { foreach (Node statement in decls.statements) { if (statement is FuncDef fdef) { Type[] argTypes = Type.EmptyTypes; if (fdef.param.Length != 0) { current_method_args = new string[fdef.param.Length]; argTypes = new Type[fdef.param.Length]; for (int i = 0; i < argTypes.Length; ++i) { argTypes[i] = ToType((TypeNode)fdef.param[i][1]); current_method_args[i] = ((Token)fdef.param[i][0]).lexeme; } } else { current_method_args = new string[] { } }; current_method_types = argTypes; cMethod = cTypeBuilder.DefineMethod(fdef.funcName.lexeme, MethodAttributes.Public | MethodAttributes.Static, ToType(fdef.funcReturnType), argTypes); if (fdef.funcName.lexeme == "main") { mainMethod = cMethod; } il = cMethod.GetILGenerator(); if (il is null) { throw new Exception("IL is null"); } localSymbols = new Dictionary <string, LocalBuilder>(); Node[] stmts = ((CodeBlock)fdef.body).statements; for (int i = 0; i < stmts.Length; ++i) { emitStatement(stmts[i], is_last: i == stmts.Length - 1); } il.Emit(OpCodes.Ret); externMethods[fdef.funcName.lexeme] = cMethod; } else if (statement is DeclareVar decl) { globalSymbols[decl.var.lexeme] = cTypeBuilder.DefineField(decl.var.lexeme, ToType(decl.type), FieldAttributes.Private | FieldAttributes.Static); il = mainInitializer.GetILGenerator(); if (!(decl.expr is null)) { AssignVar assign = new AssignVar(decl.var, decl.expr); emitExpr(assign); } } else if (statement is ExternMethod extMethod) { Type type = Type.GetType(extMethod.typeName); if (type is null) { throw new Exception($"Failed to load external type {type.Name}"); } Type[] argTypes = Type.EmptyTypes; if (extMethod.argTypes.Length != 0) { argTypes = new Type[extMethod.argTypes.Length]; for (int i = 0; i < extMethod.argTypes.Length; ++i) { argTypes[i] = ToType(extMethod.argTypes[i]); } } MethodInfo method = type.GetMethod(extMethod.methodName, argTypes); if (method is null) { throw new Exception($"Failed to load method {extMethod.methodName} from type {extMethod.typeName}"); } externMethods[extMethod.varName] = method; } } }