const table support

This commit is contained in:
Araq
2011-04-29 22:55:15 +02:00
parent ed887e67e9
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)

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"``
* 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)
* ``nimrod c koch``

View File

@@ -38,6 +38,7 @@ Boot options:
-d:tinyc include the Tiny C backend (not supported on Windows)
-d:useGnuReadline use the GNU readline library for interactive mode
(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)

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
- 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)