public Executable Compile() { var exe = new Executable(context.MachineInfo); // Put something at the zero address so we don't get 0 addresses of globals exe.AddGlobal("__zero__", CBasicType.SignedInt); // // Find Variables, Functions, Types // var cinitBody = new Block(); foreach (var tu in tus) { AddStatementDeclarations(tu); cinitBody.Statements.AddRange(tu.InitStatements); } // // Generate a function to init globals // exe.Functions.Add(new CompiledFunction("__cinit", CFunctionType.VoidProcedure, cinitBody)); // // Link everything together // This is done before compilation to make sure everything is visible (for recursion) // foreach (var tu in tus) { foreach (var g in tu.Variables) { var v = exe.AddGlobal(g.Name, g.VariableType); v.InitialValue = g.InitialValue; } exe.Functions.AddRange(tu.Functions.Where(x => x.Body != null)); } // // Compile functions // foreach (var f in exe.Functions.OfType <CompiledFunction> ()) { AddStatementDeclarations(f.Body); var c = new FunctionContext(exe, f, context); f.Body.Emit(c); f.LocalVariables.AddRange(c.LocalVariables); // Make sure it returns if (f.Body.Statements.Count == 0 || !f.Body.AlwaysReturns) { if (f.FunctionType.ReturnType.IsVoid) { c.Emit(OpCode.Return); } else { context.Report.Error(161, "'" + f.Name + "' not all code paths return a value"); } } } return(exe); }
public CInterpreter(Executable exe, int maxStack = 1024, int maxFrames = 24) { this.exe = exe; Stack = new Value[maxStack]; Frames = (from i in Enumerable.Range(0, maxFrames) select new ExecutionFrame(unusedStackFrameFunction)).ToArray(); }