const table support

This commit is contained in:
Araq 2011-04-29 22:55:15 +02:00
commit 145fabeb67
16 changed files with 116 additions and 58 deletions

View file

@ -226,6 +226,10 @@ type
TSymFlags* = set[TSymFlag] TSymFlags* = set[TSymFlag]
const
sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
type
TTypeKind* = enum # order is important! TTypeKind* = enum # order is important!
# Don't forget to change hti.nim if you make a change here # Don't forget to change hti.nim if you make a change here
# XXX put this into an include file to avoid this issue! # XXX put this into an include file to avoid this issue!

View file

@ -139,6 +139,9 @@ proc getStorageLoc(n: PNode): TStorageLoc =
of skVar: of skVar:
if sfGlobal in n.sym.flags: result = OnHeap if sfGlobal in n.sym.flags: result = OnHeap
else: result = OnStack else: result = OnStack
of skConst:
if sfGlobal in n.sym.flags: result = OnHeap
else: result = OnUnknown
else: result = OnUnknown else: result = OnUnknown
of nkDerefExpr, nkHiddenDeref: of nkDerefExpr, nkHiddenDeref:
case n.sons[0].typ.kind case n.sons[0].typ.kind
@ -1638,7 +1641,10 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
InternalError(e.info, "expr: proc not init " & sym.name.s) InternalError(e.info, "expr: proc not init " & sym.name.s)
putLocIntoDest(p, d, sym.loc) putLocIntoDest(p, d, sym.loc)
of skConst: of skConst:
if isSimpleConst(sym.typ): if sfFakeConst in sym.flags:
if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
putLocIntoDest(p, d, sym.loc)
elif isSimpleConst(sym.typ):
putIntoDest(p, d, e.typ, genLiteral(p, sym.ast, sym.typ)) putIntoDest(p, d, e.typ, genLiteral(p, sym.ast, sym.typ))
else: else:
genComplexConst(p, sym, d) genComplexConst(p, sym, d)

View file

@ -59,12 +59,7 @@ proc genVarTuple(p: BProc, n: PNode) =
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]) [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
putLocIntoDest(p, v.loc, field) putLocIntoDest(p, v.loc, field)
proc genVarStmt(p: BProc, n: PNode) = proc genSingleVar(p: BProc, a: PNode) =
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if a.kind == nkIdentDefs:
assert(a.sons[0].kind == nkSym)
var v = a.sons[0].sym var v = a.sons[0].sym
if sfGlobal in v.flags: if sfGlobal in v.flags:
assignGlobalVar(p, v) assignGlobalVar(p, v)
@ -75,17 +70,26 @@ proc genVarStmt(p: BProc, n: PNode) =
if a.sons[2].kind != nkEmpty: if a.sons[2].kind != nkEmpty:
genLineDir(p, a) genLineDir(p, a)
expr(p, a.sons[2], v.loc) expr(p, a.sons[2], v.loc)
proc genVarStmt(p: BProc, n: PNode) =
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if a.kind == nkIdentDefs:
assert(a.sons[0].kind == nkSym)
genSingleVar(p, a)
else: else:
genVarTuple(p, a) genVarTuple(p, a)
proc genConstStmt(p: BProc, t: PNode) = proc genConstStmt(p: BProc, t: PNode) =
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
if t.sons[i].kind == nkCommentStmt: continue var it = t.sons[i]
if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt") if it.kind == nkCommentStmt: continue
var c = t.sons[i].sons[0].sym if it.kind != nkConstDef: InternalError(t.info, "genConstStmt")
assert c != nil var c = it.sons[0].sym
assert c.typ != nil if sfFakeConst in c.flags:
if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags): genSingleVar(p, it)
elif c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
# generate the data: # generate the data:
fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown) fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
if sfImportc in c.flags: if sfImportc in c.flags:

View file

@ -38,7 +38,7 @@ proc mangleName(s: PSym): PRope =
of skProc, skMethod, skConverter, skConst: of skProc, skMethod, skConverter, skConst:
result = toRope("@") result = toRope("@")
of skVar: of skVar:
if (sfGlobal in s.flags): result = toRope("@") if sfGlobal in s.flags: result = toRope("@")
else: result = toRope("%") else: result = toRope("%")
of skForVar, skTemp, skParam, skType, skEnumField, skModule: of skForVar, skTemp, skParam, skType, skEnumField, skModule:
result = toRope("%") result = toRope("%")

View file

@ -15,7 +15,7 @@
import import
strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets, strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets,
msgs, os, condsyms, idents, renderer, types, passes, semfold msgs, os, condsyms, idents, renderer, types, passes, semfold, transf
type type
PStackFrame* = ref TStackFrame PStackFrame* = ref TStackFrame
@ -38,11 +38,6 @@ type
efNone, efLValue efNone, efLValue
TEvalFlags = set[TEvalFlag] TEvalFlags = set[TEvalFlag]
proc eval*(c: PEvalContext, n: PNode): PNode
# eval never returns nil! This simplifies the code a lot and
# makes it faster too.
proc evalConstExpr*(module: PSym, e: PNode): PNode
const const
evalMaxIterations = 500_000 # max iterations of all loops evalMaxIterations = 500_000 # max iterations of all loops
evalMaxRecDepth = 10_000 # max recursion depth for evaluation evalMaxRecDepth = 10_000 # max recursion depth for evaluation
@ -229,7 +224,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyFloat..tyFloat128: of tyFloat..tyFloat128:
result = newNodeIt(nkFloatLit, info, t) result = newNodeIt(nkFloatLit, info, t)
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr, of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
tyStmt, tyTypeDesc: tyStmt, tyTypeDesc, tyProc:
result = newNodeIT(nkNilLit, info, t) result = newNodeIT(nkNilLit, info, t)
of tyObject: of tyObject:
result = newNodeIT(nkPar, info, t) result = newNodeIT(nkPar, info, t)
@ -249,7 +244,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
addSon(result, p) addSon(result, p)
of tySet: of tySet:
result = newNodeIT(nkCurly, info, t) result = newNodeIT(nkCurly, info, t)
else: InternalError("getNullValue") else: InternalError("getNullValue: " & $t.kind)
proc evalVar(c: PEvalContext, n: PNode): PNode = proc evalVar(c: PEvalContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
@ -420,6 +415,7 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
# XXX what about LValue? # XXX what about LValue?
result = c.tos.params[n.sym.position + 1] result = c.tos.params[n.sym.position + 1]
of skConst: result = n.sym.ast of skConst: result = n.sym.ast
of skEnumField: result = newIntNodeT(n.sym.position, n)
else: else:
stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind) stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind)
result = emptyNode result = emptyNode
@ -1033,9 +1029,15 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
of nkPar: of nkPar:
var a = copyTree(n) var a = copyTree(n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i].sons[1], flags) var it = n.sons[i]
if it.kind == nkExprEqExpr:
result = evalAux(c, it.sons[1], flags)
if isSpecial(result): return if isSpecial(result): return
a.sons[i].sons[1] = result a.sons[i].sons[1] = result
else:
result = evalAux(c, it, flags)
if isSpecial(result): return
a.sons[i] = result
result = a result = a
of nkBracketExpr: result = evalArrayAccess(c, n, flags) of nkBracketExpr: result = evalArrayAccess(c, n, flags)
of nkDotExpr: result = evalFieldAccess(c, n, flags) of nkDotExpr: result = evalFieldAccess(c, n, flags)
@ -1078,14 +1080,17 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
InternalError(n.info, "evalAux: returned nil " & $n.kind) InternalError(n.info, "evalAux: returned nil " & $n.kind)
inc(gNestedEvals) inc(gNestedEvals)
proc eval(c: PEvalContext, n: PNode): PNode = proc eval*(c: PEvalContext, n: PNode): PNode =
## eval never returns nil! This simplifies the code a lot and
## makes it faster too.
var n = transform(c.module, n)
gWhileCounter = evalMaxIterations gWhileCounter = evalMaxIterations
gNestedEvals = evalMaxRecDepth gNestedEvals = evalMaxRecDepth
result = evalAux(c, n, {}) result = evalAux(c, n, {})
if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1): if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1):
stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ)) stackTrace(c, n, errUnhandledExceptionX, typeToString(result.typ))
proc evalConstExpr(module: PSym, e: PNode): PNode = proc evalConstExpr*(module: PSym, e: PNode): PNode =
var p = newEvalContext(module, "", true) var p = newEvalContext(module, "", true)
var s = newStackFrame() var s = newStackFrame()
s.call = e s.call = e

View file

@ -141,11 +141,11 @@ proc CommandCompileToEcmaScript(filename: string) =
proc CommandInteractive() = proc CommandInteractive() =
msgs.gErrorMax = high(int) # do not stop after first error msgs.gErrorMax = high(int) # do not stop after first error
incl(gGlobalOptions, optSafeCode) incl(gGlobalOptions, optSafeCode)
setTarget(osNimrodVM, cpuNimrodVM) #setTarget(osNimrodVM, cpuNimrodVM)
initDefines() initDefines()
DefineSymbol("nimrodvm")
registerPass(verbosePass()) registerPass(verbosePass())
registerPass(sem.semPass()) registerPass(sem.semPass())
registerPass(transf.transfPass())
registerPass(evals.evalPass()) # load system module: registerPass(evals.evalPass()) # load system module:
discard CompileModule(JoinPath(options.libpath, addFileExt("system", nimExt)), discard CompileModule(JoinPath(options.libpath, addFileExt("system", nimExt)),
false, true) false, true)

View file

@ -264,7 +264,7 @@ const
errInvalidControlFlowX: "invalid control flow: $1", errInvalidControlFlowX: "invalid control flow: $1",
errATypeHasNoValue: "a type has no value", errATypeHasNoValue: "a type has no value",
errXisNoType: "invalid type: \'$1\'", errXisNoType: "invalid type: \'$1\'",
errCircumNeedsPointer: "\'^\' needs a pointer or reference type", errCircumNeedsPointer: "'[]' needs a pointer or reference type",
errInvalidExpression: "invalid expression", errInvalidExpression: "invalid expression",
errInvalidExpressionX: "invalid expression: \'$1\'", errInvalidExpressionX: "invalid expression: \'$1\'",
errEnumHasNoValueX: "enum has no value \'$1\'", errEnumHasNoValueX: "enum has no value \'$1\'",

View file

@ -75,7 +75,7 @@ proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
if result == nil: if result == nil:
#writeln(output, renderTree(n)); #writeln(output, renderTree(n));
result = evalConstExpr(c.module, e) result = evalConstExpr(c.module, e)
if (result == nil) or (result.kind == nkEmpty): if result == nil or result.kind == nkEmpty:
GlobalError(n.info, errConstExprExpected) GlobalError(n.info, errConstExprExpected)
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =

View file

@ -338,7 +338,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
of mNaN: result = newFloatNodeT(NaN, n) of mNaN: result = newFloatNodeT(NaN, n)
of mInf: result = newFloatNodeT(Inf, n) of mInf: result = newFloatNodeT(Inf, n)
of mNegInf: result = newFloatNodeT(NegInf, n) of mNegInf: result = newFloatNodeT(NegInf, n)
else: result = copyTree(s.ast) else:
if sfFakeConst notin s.flags: result = copyTree(s.ast)
elif s.kind in {skProc, skMethod}: # BUGFIX elif s.kind in {skProc, skMethod}: # BUGFIX
result = n result = n
of nkCharLit..nkNilLit: of nkCharLit..nkNilLit:

View file

@ -337,13 +337,22 @@ proc semConst(c: PContext, n: PNode): PNode =
var v = semIdentDef(c, a.sons[0], skConst) var v = semIdentDef(c, a.sons[0], skConst)
var typ: PType = nil var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
var def = semAndEvalConstExpr(c, a.sons[2])
# check type compability between def.typ and typ: var e = semExprWithType(c, a.sons[2])
if e == nil: GlobalError(a.sons[2].info, errConstExprExpected)
var def = getConstExpr(c.module, e)
if def == nil:
v.flags.incl(sfFakeConst)
def = evalConstExpr(c.module, e)
if def == nil or def.kind == nkEmpty: def = e
# check type compatibility between def.typ and typ:
if typ != nil: if typ != nil:
def = fitRemoveHiddenConv(c, typ, def) def = fitRemoveHiddenConv(c, typ, def)
else: else:
typ = def.typ typ = def.typ
if not typeAllowed(typ, skConst): if not typeAllowed(typ, skConst):
v.flags.incl(sfFakeConst)
if not typeAllowed(typ, skVar):
GlobalError(a.info, errXisNoType, typeToString(typ)) GlobalError(a.info, errXisNoType, typeToString(typ))
v.typ = typ v.typ = typ
v.ast = def # no need to copy v.ast = def # no need to copy

View file

@ -17,7 +17,7 @@
# * introduces method dispatchers # * introduces method dispatchers
import import
strutils, lists, options, ast, astalgo, trees, treetab, evals, msgs, os, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, passes, semfold, magicsys, cgmeth idents, renderer, types, passes, semfold, magicsys, cgmeth
const const
@ -178,8 +178,8 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
result = b result = b
case b.sym.kind case b.sym.kind
of skConst, skEnumField: of skConst, skEnumField:
# BUGFIX: skEnumField was missing if sfFakeConst notin b.sym.flags:
if not (skipTypes(b.sym.typ, abstractInst).kind in ConstantDataTypes): if skipTypes(b.sym.typ, abstractInst).kind notin ConstantDataTypes:
result = getConstExpr(c.module, b) result = getConstExpr(c.module, b)
if result == nil: InternalError(b.info, "transformSym: const") if result == nil: InternalError(b.info, "transformSym: const")
else: else:
@ -223,6 +223,26 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
defs[L-1] = transform(c, it.sons[L-1]) defs[L-1] = transform(c, it.sons[L-1])
result[i] = defs result[i] = defs
proc transformConstSection(c: PTransf, v: PNode): PTransNode =
result = newTransNode(v)
for i in countup(0, sonsLen(v)-1):
var it = v.sons[i]
if it.kind == nkCommentStmt:
result[i] = PTransNode(it)
else:
if it.kind != nkConstDef: InternalError(it.info, "transformConstSection")
if it.sons[0].kind != nkSym:
InternalError(it.info, "transformConstSection")
if sfFakeConst in it[0].sym.flags:
var b = newNodeI(nkConstDef, it.info)
addSon(b, it[0])
addSon(b, ast.emptyNode) # no type description
addSon(b, transform(c, it[2]).pnode)
result[i] = PTransNode(b)
else:
result[i] = PTransNode(it)
proc hasContinue(n: PNode): bool = proc hasContinue(n: PNode): bool =
case n.kind case n.kind
of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
@ -532,7 +552,7 @@ proc addFormalParam(routine: PSym, param: PSym) =
addSon(routine.ast.sons[paramsPos], newSymNode(param)) addSon(routine.ast.sons[paramsPos], newSymNode(param))
proc indirectAccess(a, b: PSym): PNode = proc indirectAccess(a, b: PSym): PNode =
# returns a^ .b as a node # returns a[].b as a node
var x = newSymNode(a) var x = newSymNode(a)
var y = newSymNode(b) var y = newSymNode(b)
var deref = newNodeI(nkHiddenDeref, x.info) var deref = newNodeI(nkHiddenDeref, x.info)
@ -700,7 +720,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
return n.ptransNode return n.ptransNode
of nkConstSection: of nkConstSection:
# do not replace ``const c = 3`` with ``const 3 = 3`` # do not replace ``const c = 3`` with ``const 3 = 3``
return n.ptransNode return transformConstSection(c, n)
of nkVarSection: of nkVarSection:
if c.inlining > 0: if c.inlining > 0:
# we need to copy the variables for multiple yield statements: # we need to copy the variables for multiple yield statements:
@ -722,6 +742,7 @@ proc processTransf(context: PPassContext, n: PNode): PNode =
# Note: For interactive mode we cannot call 'passes.skipCodegen' and skip # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip
# this step! We have to rely that the semantic pass transforms too errornous # this step! We have to rely that the semantic pass transforms too errornous
# nodes into an empty node. # nodes into an empty node.
if passes.skipCodegen(n): return n
var c = PTransf(context) var c = PTransf(context)
pushTransCon(c, newTransCon(getCurrOwner(c))) pushTransCon(c, newTransCon(getCurrOwner(c)))
result = PNode(transform(c, n)) result = PNode(transform(c, n))
@ -740,3 +761,7 @@ proc transfPass(): TPass =
result.process = processTransf result.process = processTransf
result.close = processTransf # we need to process generics too! result.close = processTransf # we need to process generics too!
proc transform*(module: PSym, n: PNode): PNode =
var c = openTransf(module, "")
result = processTransf(c, n)

View file

@ -12,7 +12,8 @@ To get the source code you need either of these:
``wget --no-check-certificate "https://github.com/Araq/Nimrod/tarball/master"`` ``wget --no-check-certificate "https://github.com/Araq/Nimrod/tarball/master"``
* git: ``git clone git://github.com/Araq/Nimrod.git`` * git: ``git clone git://github.com/Araq/Nimrod.git``
After downloading the source (and extracting it), you need to extract build/csources.zip then you can bootstrap with: After downloading the source (and extracting it), you need to
extract ``build/csources.zip`` and then you can bootstrap with:
* ``./build.sh`` or ``build.bat`` (Windows) * ``./build.sh`` or ``build.bat`` (Windows)
* ``nimrod c koch`` * ``nimrod c koch``

View file

@ -38,6 +38,7 @@ Boot options:
-d:tinyc include the Tiny C backend (not supported on Windows) -d:tinyc include the Tiny C backend (not supported on Windows)
-d:useGnuReadline use the GNU readline library for interactive mode -d:useGnuReadline use the GNU readline library for interactive mode
(not needed on Windows) (not needed on Windows)
-d:nativeStacktrace use native stack traces (only for Mac OS X or Linux)
""" """
proc exe(f: string): string = return addFileExt(f, ExeExt) proc exe(f: string): string = return addFileExt(f, ExeExt)

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf # (c) Copyright 2011 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -210,7 +210,7 @@ proc `$`*(t: PStringTable): string {.rtl, extern: "nstDollar".} =
result.add("}") result.add("}")
when isMainModule: when isMainModule:
var x = {"k": "v", "11": "22", "565": "67"}.newStringTable const x = {"k": "v", "11": "22", "565": "67"}.newStringTable
assert x["k"] == "v" assert x["k"] == "v"
assert x["11"] == "22" assert x["11"] == "22"
assert x["565"] == "67" assert x["565"] == "67"

View file

@ -61,10 +61,10 @@ proc popCurrentException {.compilerRtl, inl.} =
# some platforms have native support for stack traces: # some platforms have native support for stack traces:
const const
nativeStackTrace = (defined(macosx) or defined(linux)) and nativeStackTraceSupported = (defined(macosx) or defined(linux)) and
not nimrodStackTrace not nimrodStackTrace
when nativeStacktrace: when nativeStacktrace and nativeStackTraceSupported:
type type
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>", TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
final, pure.} = object final, pure.} = object
@ -165,7 +165,7 @@ proc rawWriteStackTrace(s: var string) =
add(s, "Traceback (most recent call last)") add(s, "Traceback (most recent call last)")
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
auxWriteStackTrace(framePtr, s) auxWriteStackTrace(framePtr, s)
elif nativeStackTrace: elif nativeStackTrace and nativeStackTraceSupported:
add(s, "Traceback from system (most recent call last)") add(s, "Traceback from system (most recent call last)")
add(s, stackTraceNewLine) add(s, stackTraceNewLine)
auxWriteStackTraceWithBacktrace(s) auxWriteStackTraceWithBacktrace(s)

View file

@ -1,5 +1,7 @@
- clean up the tests! - clean up the tests!
- fake-consts, implicit ref/ptr->var conversion - implicit ref/ptr->var conversion
- warning for implicit openArray -> varargs convention
- implement explicit varargs
High priority (version 0.9.0) High priority (version 0.9.0)