public FunctionUnit MainFunctionUnit(string p_name) { FunctionUnit this_function_unit = new FunctionUnit(p_name, ModuleName); this_function_unit.Set(0, Body, ChunkPosition, 0); return(this_function_unit); }
private void CompileFunction(string p_name, FunctionExpressionNode p_node, bool p_isGlobal) { FunctionUnit new_function = new FunctionUnit(p_name, moduleName); Operand this_address = (Operand)AddData(new_function); if (p_node.Type != NodeType.FUNCTION_DECLARATION) { Add(OpCode.DECLARE_FUNCTION, 0, 1, this_address, p_node.PositionData); } else { if (p_isGlobal) { Add(OpCode.DECLARE_FUNCTION, 0, 0, this_address, p_node.PositionData);// zero for gloabal } else { Add(OpCode.DECLARE_FUNCTION, 1, 0, this_address, p_node.PositionData);// one for current env } } // body int function_start = instructionCounter; // env env.Add(new List <string>()); Add(OpCode.OPEN_ENV, p_node.PositionData); //Add funStartEnv funStartEnv.Push(env.Count - 1); int exit_instruction_address = instructionCounter; Add(OpCode.RETURN_SET, 0, p_node.PositionData); Operand arity = 0; if (p_node.Parameters != null) { foreach (string p in p_node.Parameters) { SetVar(p);// it is always local Add(OpCode.DECLARE_VARIABLE, p_node.PositionData); arity++; } } upvalueStack.Push(new List <Variable>()); foreach (Node n in p_node.Body) { ChunkIt(n); } bool is_closure = false; if (upvalueStack.Peek().Count != 0) { is_closure = true; List <Variable> this_variables = upvalueStack.Pop(); List <UpValueUnit> new_upvalues = new List <UpValueUnit>(); foreach (Variable v in this_variables) { new_upvalues.Add(new UpValueUnit((Operand)v.address, (Operand)v.envIndex)); } ClosureUnit new_closure = new ClosureUnit(new_function, new_upvalues); chunk.SwapDataLiteral(this_address, new Unit(new_closure)); } else { upvalueStack.Pop(); } // fix the exit address chunk.FixInstruction(exit_instruction_address, null, (Operand)(instructionCounter - exit_instruction_address), null, null); if (is_closure == true) { Add(OpCode.CLOSE_CLOSURE, p_node.PositionData); } else { Add(OpCode.CLOSE_FUNCTION, p_node.PositionData); } new_function.Set( arity, chunk.Slice(function_start, instructionCounter), chunk.ChunkPosition.Slice(function_start, instructionCounter), (Operand)function_start); instructionCounter = function_start; //Console.WriteLine("Removed env"); env.RemoveAt(env.Count - 1); //pop fun start env funStartEnv.Pop(); }