mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-02 19:22:40 +00:00
const table support
This commit is contained in:
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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("%")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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\'",
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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``
|
||||
|
||||
1
koch.nim
1
koch.nim
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user