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]
const
sfFakeConst* = sfDeadCodeElim # const cannot be put into a data section
type
TTypeKind* = enum # order is important!
# Don't forget to change hti.nim if you make a change here
# XXX put this into an include file to avoid this issue!

View file

@ -139,6 +139,9 @@ proc getStorageLoc(n: PNode): TStorageLoc =
of skVar:
if sfGlobal in n.sym.flags: result = OnHeap
else: result = OnStack
of skConst:
if sfGlobal in n.sym.flags: result = OnHeap
else: result = OnUnknown
else: result = OnUnknown
of nkDerefExpr, nkHiddenDeref:
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)
putLocIntoDest(p, d, sym.loc)
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))
else:
genComplexConst(p, sym, d)

View file

@ -59,33 +59,37 @@ proc genVarTuple(p: BProc, n: PNode) =
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
putLocIntoDest(p, v.loc, field)
proc genSingleVar(p: BProc, a: PNode) =
var v = a.sons[0].sym
if sfGlobal in v.flags:
assignGlobalVar(p, v)
genObjectInit(p, cpsInit, v.typ, v.loc, true)
else:
assignLocalVar(p, v)
initVariable(p, v)
if a.sons[2].kind != nkEmpty:
genLineDir(p, a)
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)
var v = a.sons[0].sym
if sfGlobal in v.flags:
assignGlobalVar(p, v)
genObjectInit(p, cpsInit, v.typ, v.loc, true)
else:
assignLocalVar(p, v)
initVariable(p, v)
if a.sons[2].kind != nkEmpty:
genLineDir(p, a)
expr(p, a.sons[2], v.loc)
else:
genSingleVar(p, a)
else:
genVarTuple(p, a)
proc genConstStmt(p: BProc, t: PNode) =
for i in countup(0, sonsLen(t) - 1):
if t.sons[i].kind == nkCommentStmt: continue
if t.sons[i].kind != nkConstDef: InternalError(t.info, "genConstStmt")
var c = t.sons[i].sons[0].sym
assert c != nil
assert c.typ != nil
if c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
var it = t.sons[i]
if it.kind == nkCommentStmt: continue
if it.kind != nkConstDef: InternalError(t.info, "genConstStmt")
var c = it.sons[0].sym
if sfFakeConst in c.flags:
genSingleVar(p, it)
elif c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags):
# generate the data:
fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
if sfImportc in c.flags:

View file

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

View file

@ -15,7 +15,7 @@
import
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
PStackFrame* = ref TStackFrame
@ -38,11 +38,6 @@ type
efNone, efLValue
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
evalMaxIterations = 500_000 # max iterations of all loops
evalMaxRecDepth = 10_000 # max recursion depth for evaluation
@ -229,7 +224,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
of tyFloat..tyFloat128:
result = newNodeIt(nkFloatLit, info, t)
of tyVar, tyPointer, tyPtr, tyRef, tyCString, tySequence, tyString, tyExpr,
tyStmt, tyTypeDesc:
tyStmt, tyTypeDesc, tyProc:
result = newNodeIT(nkNilLit, info, t)
of tyObject:
result = newNodeIT(nkPar, info, t)
@ -249,7 +244,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
addSon(result, p)
of tySet:
result = newNodeIT(nkCurly, info, t)
else: InternalError("getNullValue")
else: InternalError("getNullValue: " & $t.kind)
proc evalVar(c: PEvalContext, n: PNode): PNode =
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?
result = c.tos.params[n.sym.position + 1]
of skConst: result = n.sym.ast
of skEnumField: result = newIntNodeT(n.sym.position, n)
else:
stackTrace(c, n, errCannotInterpretNodeX, $n.sym.kind)
result = emptyNode
@ -1033,9 +1029,15 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
of nkPar:
var a = copyTree(n)
for i in countup(0, sonsLen(n) - 1):
result = evalAux(c, n.sons[i].sons[1], flags)
if isSpecial(result): return
a.sons[i].sons[1] = result
var it = n.sons[i]
if it.kind == nkExprEqExpr:
result = evalAux(c, it.sons[1], flags)
if isSpecial(result): return
a.sons[i].sons[1] = result
else:
result = evalAux(c, it, flags)
if isSpecial(result): return
a.sons[i] = result
result = a
of nkBracketExpr: result = evalArrayAccess(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)
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
gNestedEvals = evalMaxRecDepth
result = evalAux(c, n, {})
if (result.kind == nkExceptBranch) and (sonsLen(result) >= 1):
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 s = newStackFrame()
s.call = e

View file

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

View file

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

View file

@ -75,7 +75,7 @@ proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
if result == nil:
#writeln(output, renderTree(n));
result = evalConstExpr(c.module, e)
if (result == nil) or (result.kind == nkEmpty):
if result == nil or result.kind == nkEmpty:
GlobalError(n.info, errConstExprExpected)
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 mInf: result = newFloatNodeT(Inf, 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
result = n
of nkCharLit..nkNilLit:

View file

@ -337,14 +337,23 @@ proc semConst(c: PContext, n: PNode): PNode =
var v = semIdentDef(c, a.sons[0], skConst)
var typ: PType = 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:
def = fitRemoveHiddenConv(c, typ, def)
else:
typ = def.typ
if not typeAllowed(typ, skConst):
GlobalError(a.info, errXisNoType, typeToString(typ))
v.flags.incl(sfFakeConst)
if not typeAllowed(typ, skVar):
GlobalError(a.info, errXisNoType, typeToString(typ))
v.typ = typ
v.ast = def # no need to copy
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)

View file

@ -17,7 +17,7 @@
# * introduces method dispatchers
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
const
@ -178,10 +178,10 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
result = b
case b.sym.kind
of skConst, skEnumField:
# BUGFIX: skEnumField was missing
if not (skipTypes(b.sym.typ, abstractInst).kind in ConstantDataTypes):
result = getConstExpr(c.module, b)
if result == nil: InternalError(b.info, "transformSym: const")
if sfFakeConst notin b.sym.flags:
if skipTypes(b.sym.typ, abstractInst).kind notin ConstantDataTypes:
result = getConstExpr(c.module, b)
if result == nil: InternalError(b.info, "transformSym: const")
else:
nil
@ -223,6 +223,26 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
defs[L-1] = transform(c, it.sons[L-1])
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 =
case n.kind
of nkEmpty..nkNilLit, nkForStmt, nkWhileStmt: nil
@ -532,7 +552,7 @@ proc addFormalParam(routine: PSym, param: PSym) =
addSon(routine.ast.sons[paramsPos], newSymNode(param))
proc indirectAccess(a, b: PSym): PNode =
# returns a^ .b as a node
# returns a[].b as a node
var x = newSymNode(a)
var y = newSymNode(b)
var deref = newNodeI(nkHiddenDeref, x.info)
@ -698,9 +718,9 @@ proc transform(c: PTransf, n: PNode): PTransNode =
result = PTransNode(newNode(nkCommentStmt))
of nkCommentStmt, nkTemplateDef:
return n.ptransNode
of nkConstSection:
of nkConstSection:
# do not replace ``const c = 3`` with ``const 3 = 3``
return n.ptransNode
return transformConstSection(c, n)
of nkVarSection:
if c.inlining > 0:
# 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
# this step! We have to rely that the semantic pass transforms too errornous
# nodes into an empty node.
if passes.skipCodegen(n): return n
var c = PTransf(context)
pushTransCon(c, newTransCon(getCurrOwner(c)))
result = PNode(transform(c, n))
@ -740,3 +761,7 @@ proc transfPass(): TPass =
result.process = processTransf
result.close = processTransf # we need to process generics too!
proc transform*(module: PSym, n: PNode): PNode =
var c = openTransf(module, "")
result = processTransf(c, n)