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);
            }
        }
Example #2
0
        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;
                }
            }
        }