From 6a9baf3fd7842027a30ee4856d40841610dccc13 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 15 Oct 2013 08:06:54 +0200 Subject: compiler bootstraps with new VM --- compiler/main.nim | 2 +- compiler/sem.nim | 43 +++++++++++++-------------- compiler/semdata.nim | 2 +- compiler/semexprs.nim | 6 ++-- compiler/semmagic.nim | 17 +++++++++++ compiler/semstmts.nim | 4 +-- compiler/vm.nim | 80 ++++++++++++++++++++++++++++++++++----------------- compiler/vmdef.nim | 18 ++++++++++++ compiler/vmgen.nim | 23 ++++++++++----- todo.txt | 5 ++-- web/news.txt | 5 +++- 11 files changed, 141 insertions(+), 64 deletions(-) diff --git a/compiler/main.nim b/compiler/main.nim index 7cfc6d406..7124b6984 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -14,7 +14,7 @@ import os, condsyms, rodread, rodwrite, times, wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, jsgen, json, nversion, - platform, nimconf, importer, passaux, depends, evals, types, idgen, + platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen, tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists, pretty diff --git a/compiler/sem.nim b/compiler/sem.nim index 71951dd3f..89f87acaa 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -14,7 +14,7 @@ import wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math, magicsys, parser, nversion, nimsets, semfold, importer, procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch, - semthreads, intsets, transf, evals, idgen, aliases, cgmeth, lambdalifting, + semthreads, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2 # implementation @@ -149,25 +149,26 @@ proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode = result = newSymNode(symFromType(t, info), info) result.typ = makeTypeDesc(c, t) -proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext = - result = newEvalContext(c.module, mode) - result.getType = proc (n: PNode): PNode = - var e = tryExpr(c, n) - if e == nil: - result = symNodeFromType(c, errorType(c), n.info) - elif e.typ == nil: - result = newSymNode(getSysSym"void") - else: - result = symNodeFromType(c, e.typ, n.info) +when false: + proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext = + result = newEvalContext(c.module, mode) + result.getType = proc (n: PNode): PNode = + var e = tryExpr(c, n) + if e == nil: + result = symNodeFromType(c, errorType(c), n.info) + elif e.typ == nil: + result = newSymNode(getSysSym"void") + else: + result = symNodeFromType(c, e.typ, n.info) - result.handleIsOperator = proc (n: PNode): PNode = - result = IsOpImpl(c, n) + result.handleIsOperator = proc (n: PNode): PNode = + result = IsOpImpl(c, n) -proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode = - result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e) + proc evalConstExpr(c: PContext, module: PSym, e: PNode): PNode = + result = evalConstExprAux(c.createEvalContext(emConst), module, nil, e) -proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode = - result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e) + proc evalStaticExpr(c: PContext, module: PSym, e: PNode, prc: PSym): PNode = + result = evalConstExprAux(c.createEvalContext(emStatic), module, prc, e) proc semConstExpr(c: PContext, n: PNode): PNode = var e = semExprWithType(c, n) @@ -176,7 +177,7 @@ proc semConstExpr(c: PContext, n: PNode): PNode = return n result = getConstExpr(c.module, e) if result == nil: - result = evalConstExpr(c, c.module, e) + result = evalConstExpr(c.module, e) if result == nil or result.kind == nkEmpty: if e.info != n.info: pushInfoContext(n.info) @@ -222,10 +223,10 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, if sym == c.p.owner: GlobalError(n.info, errRecursiveDependencyX, sym.name.s) - if c.evalContext == nil: - c.evalContext = c.createEvalContext(emStatic) + #if c.evalContext == nil: + # c.evalContext = c.createEvalContext(emStatic) - result = evalMacroCall(c.evalContext, n, nOrig, sym) + result = evalMacroCall(c.module, n, nOrig, sym) if semCheck: result = semAfterMacroCall(c, result, sym) proc forceBool(c: PContext, n: PNode): PNode = diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 121bf297d..9ab365c9d 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -13,7 +13,7 @@ import strutils, lists, intsets, options, lexer, ast, astalgo, trees, treetab, wordrecg, ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math, - magicsys, nversion, nimsets, parser, times, passes, rodread, evals + magicsys, nversion, nimsets, parser, times, passes, rodread, vmdef type TOptionEntry* = object of lists.TListEntry # entries to put on a diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 47e07d402..b5d3ced66 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -631,18 +631,18 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = call.add(a) #echo "NOW evaluating at compile time: ", call.renderTree if sfCompileTime in callee.flags: - result = evalStaticExpr(c, c.module, call, c.p.owner) + result = evalStaticExpr(c.module, call, c.p.owner) if result.isNil: LocalError(n.info, errCannotInterpretNodeX, renderTree(call)) else: - result = evalConstExpr(c, c.module, call) + result = evalConstExpr(c.module, call) if result.isNil: result = n #if result != n: # echo "SUCCESS evaluated at compile time: ", call.renderTree proc semStaticExpr(c: PContext, n: PNode): PNode = let a = semExpr(c, n.sons[0]) - result = evalStaticExpr(c, c.module, a, c.p.owner) + result = evalStaticExpr(c.module, a, c.p.owner) if result.isNil: LocalError(n.info, errCannotInterpretNodeX, renderTree(n)) result = emptyNode diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 88567b10a..44e106678 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -32,6 +32,23 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode = result.add(filename) result.add(line) + +proc evalTypeTrait(trait, operand: PNode, context: PSym): PNode = + InternalAssert operand.kind == nkSym + + let typ = operand.sym.typ.skipTypes({tyTypeDesc}) + case trait.sym.name.s.normalize + of "name": + result = newStrNode(nkStrLit, typ.typeToString(preferName)) + result.typ = newType(tyString, context) + result.info = trait.info + of "arity": + result = newIntNode(nkIntLit, typ.n.len-1) + result.typ = newType(tyInt, context) + result.info = trait.info + else: + internalAssert false + proc semTypeTraits(c: PContext, n: PNode): PNode = checkMinSonsLen(n, 2) internalAssert n.sons[1].kind == nkSym diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ed6787a16..4fc69043b 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1152,14 +1152,14 @@ proc setLine(n: PNode, info: TLineInfo) = proc semPragmaBlock(c: PContext, n: PNode): PNode = let pragmaList = n.sons[0] pragma(c, nil, pragmaList, exprPragmas) - result = semStmt(c, n.sons[1]) + result = semExpr(c, n.sons[1]) for i in 0 .. 100: + inc(evalMacroCounter) + if evalMacroCounter > 100: GlobalError(n.info, errTemplateInstantiationTooNested) + setupGlobalCtx(module) + var c = globalCtx c.callsite = nOrig - let body = optBody(c, sym) - let start = genStmt(c, body) + let start = genProc(c, sym) var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil) newSeq(tos.slots, c.prc.maxSlots) @@ -917,8 +944,9 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode = tos.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0]) # setup parameters: for i in 1 .. < L: tos.slots[i] = setupMacroParam(n.sons[i]) - rawExecute(c, start, tos) - result = tos.slots[0] + # temporary storage: + for i in L .. = 0: InternalError(n.info, "not unused") + if x >= 0: + #debug(n) + InternalError(n.info, "not unused") proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) = let tmp = c.genx(arg) @@ -508,7 +510,7 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) = let tmp = c.genx(n.sons[1]) if dest < 0: dest = c.getTemp(n.typ) c.genSetType(n.sons[1], tmp) - c.gABC(n, opc, dest, tmp) + c.gABC(n, opcCard, dest, tmp) c.freeTemp(tmp) proc genMagic(c: PCtx; n: PNode; dest: var TDest) = @@ -701,7 +703,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mTypeTrait: let tmp = c.genx(n.sons[1]) if dest < 0: dest = c.getTemp(n.typ) - c.gABx(n, opcSetType, tmp, c.genType(n.sons[1])) + c.gABx(n, opcSetType, tmp, c.genType(n.sons[1].typ)) c.gABC(n, opcTypeTrait, dest, tmp) c.freeTemp(tmp) of mIs: @@ -1259,7 +1261,14 @@ proc optimizeJumps(c: PCtx; start: int) = proc genProc(c: PCtx; s: PSym): int = let x = s.ast.sons[optimizedCodePos] if x.kind == nkEmpty: - c.removeLastEof + #echo "GENERATING CODE FOR ", s.name.s + let last = c.code.len-1 + var eofInstr: TInstr + if last >= 0 and c.code[last].opcode == opcEof: + eofInstr = c.code[last] + c.code.setLen(last) + c.debug.setLen(last) + #c.removeLastEof result = c.code.len+1 # skip the jump instruction s.ast.sons[optimizedCodePos] = newIntNode(nkIntLit, result) # thanks to the jmp we can add top level statements easily and also nest @@ -1275,9 +1284,9 @@ proc genProc(c: PCtx; s: PSym): int = # generate final 'return' statement: c.gABC(body, opcRet) c.patch(procStart) - c.gABC(body, opcEof) + + c.gABC(body, opcEof, eofInstr.regA) s.position = c.prc.maxSlots c.prc = oldPrc - #c.echoCode else: result = x.intVal.int diff --git a/todo.txt b/todo.txt index da7585500..647f5e2c1 100644 --- a/todo.txt +++ b/todo.txt @@ -2,8 +2,9 @@ version 0.9.4 ============= - new VM: - - implement the glue to replace evals.nim - - implement missing magics + - new VM requires lambda lifting + - codegen for computed goto still wrong + - test and activate the jump optimizer - implement overflow checking - implement the FFI diff --git a/web/news.txt b/web/news.txt index 1b492fa97..7bb0676ee 100644 --- a/web/news.txt +++ b/web/news.txt @@ -41,6 +41,9 @@ Compiler Additions over the generated code. - The compiler now supports a ``computedGoto`` pragma to support very fast dispatching for interpreters and the like. +- The old evaluation engine has been replaced by a proper register based + virtual machine. This fixes numerous bugs for ``nimrod i`` and for macro + evaluation. Language Additions @@ -55,7 +58,7 @@ Language Additions OOP-like syntactic sugar. - Added ``delegator pragma`` for handling calls to missing procs and fields at compile-time. -- Support for user-defined type classes have been added. +- Support for user-defined type classes has been added. Tools improvements -- cgit 1.4.1-2-gfad0