private static void initCompiler(ref Compiler_t compiler, FunctionType type, Token funcName) { compiler.enclosing = current; compiler.function = null; compiler.type = type; compiler.localCount = 0; compiler.scopeDepth = 0; compiler.function = Object.newFunction(); current = compiler; if (type != FunctionType.TYPE_SCRIPT) { current.function.name = Object.copyString(funcName._char_ptr, funcName.start, funcName.length); } Local local = current.locals[current.localCount++]; local.depth = 0; local.isCaptured = false; if (type != FunctionType.TYPE_FUNCTION) { local.name._char_ptr = "this\0".ToCharArray(); local.name.start = 0; local.name.length = 4; } else { local.name._char_ptr = new char[] { '\0' }; local.name.start = 0; local.name.length = 0; } current.locals[current.localCount - 1] = local; // C sharp fix. }
void function(Stmt.Function funStmt, FunctionType type) { /* clox: funDeclaration */ byte global = 0; if (type == FunctionType.TYPE_FUNCTION) { global = parseVariable(funStmt.name, "Expect function name."); markInitialized(); } /* clox: function */ Compiler_t compiler = new Compiler_t(); initCompiler(ref compiler, type, funStmt.name); captureToken(funStmt.name); beginScope(); // Compile parameter list. if (funStmt.params_.Count > 255) { errorAtCurrent("Cannot have more than 255 parameters."); } foreach (Token param in funStmt.params_) { byte paramConstant = parseVariable(param, "Expect parameter name."); defineVariable(paramConstant); } current.function.arity = funStmt.params_.Count; // Compile the function body. foreach (Stmt stmt in funStmt.body) { compile(stmt); } // Create the function object. ObjFunction function = endCompiler(); emitBytes((byte)OpCode.OP_CLOSURE, makeConstant(Value.OBJ_VAL(function))); for (int i = 0; i < function.upvalueCount; i++) { emitByte((byte)(compiler.upvalues[i].isLocal ? 1 : 0)); emitByte(compiler.upvalues[i].index); } /* clox: funDeclaration */ if (type == FunctionType.TYPE_FUNCTION) { defineVariable(global); } }
public static void markCompilerRoots() { Compiler_t compiler = current; while (compiler != null) { Memory.markObject((Obj)compiler.function); compiler = compiler.enclosing; } }
private static int resolveLocal(ref Compiler_t compiler, Token name) { for (int i = compiler.localCount - 1; i >= 0; i--) { Local local = compiler.locals[i]; if (identifiersEqual(name, local.name)) { if (local.depth == -1) { error("Cannot read local variable in its own initializer."); } return(i); } } return(-1); }
private static ObjFunction endCompiler() { emitReturn(); ObjFunction function = current.function; #if DEBUG_PRINT_CODE if (!hadError) { Chunk_t _chunk = currentChunk(); Debug.disassembleChunk(ref _chunk, function.name != null ? function.name.chars : "<script>\0".ToCharArray()); } #endif current = current.enclosing; return(function); }
/*** VISITOR COMPILER ***/ public ObjFunction compile() { Compiler_t compiler = new Compiler_t(); Token t = new Token { line = 1 }; initCompiler(ref compiler, FunctionType.TYPE_SCRIPT, t); captureToken(t); foreach (Stmt stmt in statements) { compile(stmt); } ObjFunction function = endCompiler(); return(hadError ? null : function); }
private static int addUpvalue(ref Compiler_t compiler, byte index, bool isLocal) { int upvalueCount = compiler.function.upvalueCount; for (int i = 0; i < upvalueCount; i++) { Upvalue upvalue = compiler.upvalues[i]; if (upvalue.index == index && upvalue.isLocal == isLocal) { return(i); } } if (upvalueCount == UINT8_COUNT) { error("Too many closure variables in function."); return(0); } compiler.upvalues[upvalueCount].isLocal = isLocal; compiler.upvalues[upvalueCount].index = index; return(compiler.function.upvalueCount++); }
private static int resolveUpvalue(ref Compiler_t compiler, Token name) { if (compiler.enclosing == null) { return(-1); } int local = resolveLocal(ref compiler.enclosing, name); if (local != -1) { compiler.enclosing.locals[local].isCaptured = true; return(addUpvalue(ref compiler, (byte)local, true)); } int upvalue = resolveUpvalue(ref compiler.enclosing, name); if (upvalue != -1) { return(addUpvalue(ref compiler, (byte)upvalue, false)); } return(-1); }