Merge branch 'vm2_2' into devel
This commit is contained in:
commit
20131c32af
21 changed files with 976 additions and 577 deletions
|
|
@ -62,7 +62,7 @@ type
|
||||||
nkTripleStrLit, # a triple string literal """
|
nkTripleStrLit, # a triple string literal """
|
||||||
nkNilLit, # the nil literal
|
nkNilLit, # the nil literal
|
||||||
# end of atoms
|
# end of atoms
|
||||||
nkMetaNode, # difficult to explain; represents itself
|
nkMetaNode_Obsolete, # difficult to explain; represents itself
|
||||||
# (used for macros)
|
# (used for macros)
|
||||||
nkDotCall, # used to temporarily flag a nkCall node;
|
nkDotCall, # used to temporarily flag a nkCall node;
|
||||||
# this is used
|
# this is used
|
||||||
|
|
@ -1112,10 +1112,6 @@ proc newNodeIT(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
|
||||||
result.info = info
|
result.info = info
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
proc newMetaNodeIT*(tree: PNode, info: TLineInfo, typ: PType): PNode =
|
|
||||||
result = newNodeIT(nkMetaNode, info, typ)
|
|
||||||
result.add(tree)
|
|
||||||
|
|
||||||
var emptyParams = newNode(nkFormalParams)
|
var emptyParams = newNode(nkFormalParams)
|
||||||
emptyParams.addSon(emptyNode)
|
emptyParams.addSon(emptyNode)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,9 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
|
||||||
appf(result, ",$N$1\"floatVal\": $2",
|
appf(result, ",$N$1\"floatVal\": $2",
|
||||||
[istr, toRope(n.floatVal.toStrMaxPrecision)])
|
[istr, toRope(n.floatVal.toStrMaxPrecision)])
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
if n.strVal.isNil:
|
||||||
|
appf(result, ",$N$1\"strVal\": null", [istr])
|
||||||
|
else:
|
||||||
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
appf(result, ",$N$1\"sym\": $2",
|
appf(result, ",$N$1\"sym\": $2",
|
||||||
|
|
@ -407,6 +410,9 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
|
||||||
appf(result, ",$N$1\"floatVal\": $2",
|
appf(result, ",$N$1\"floatVal\": $2",
|
||||||
[istr, toRope(n.floatVal.toStrMaxPrecision)])
|
[istr, toRope(n.floatVal.toStrMaxPrecision)])
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
if n.strVal.isNil:
|
||||||
|
appf(result, ",$N$1\"strVal\": null", [istr])
|
||||||
|
else:
|
||||||
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
appf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
appf(result, ",$N$1\"sym\": $2_$3",
|
appf(result, ",$N$1\"sym\": $2_$3",
|
||||||
|
|
|
||||||
288
compiler/canonicalizer.nim
Normal file
288
compiler/canonicalizer.nim
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The Nimrod Compiler
|
||||||
|
# (c) Copyright 2014 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## This module implements the canonalization for the various caching mechanisms.
|
||||||
|
|
||||||
|
import strutils, db_sqlite, md5
|
||||||
|
|
||||||
|
var db: TDbConn
|
||||||
|
|
||||||
|
# We *hash* the relevant information into 128 bit hashes. This should be good enough
|
||||||
|
# to prevent any collisions.
|
||||||
|
|
||||||
|
type
|
||||||
|
TUid = distinct MD5Digest
|
||||||
|
|
||||||
|
# For name mangling we encode these hashes via a variant of base64 (called
|
||||||
|
# 'base64a') and prepend the *primary* identifier to ease the debugging pain.
|
||||||
|
# So a signature like:
|
||||||
|
#
|
||||||
|
# proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt)
|
||||||
|
#
|
||||||
|
# is mangled into:
|
||||||
|
# gABI_MTdmOWY5MTQ1MDcyNGQ3ZA
|
||||||
|
#
|
||||||
|
# This is a good compromise between correctness and brevity. ;-)
|
||||||
|
|
||||||
|
const
|
||||||
|
cb64 = [
|
||||||
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||||
|
"O", "P", "Q", "R", "S", "T" "U", "V", "W", "X", "Y", "Z",
|
||||||
|
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
|
||||||
|
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||||
|
"_A", "_B"]
|
||||||
|
|
||||||
|
proc toBase64a(s: cstring, len: int): string =
|
||||||
|
## encodes `s` into base64 representation. After `lineLen` characters, a
|
||||||
|
## `newline` is added.
|
||||||
|
var total = ((len + 2) div 3) * 4
|
||||||
|
result = newStringOfCap(total)
|
||||||
|
var i = 0
|
||||||
|
while i < s.len - 2:
|
||||||
|
let a = ord(s[i])
|
||||||
|
let b = ord(s[i+1])
|
||||||
|
let c = ord(s[i+2])
|
||||||
|
result.add cb64[a shr 2]
|
||||||
|
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
||||||
|
result.add cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)]
|
||||||
|
result.add cb64[c and 0x3F]
|
||||||
|
inc(i, 3)
|
||||||
|
if i < s.len-1:
|
||||||
|
let a = ord(s[i])
|
||||||
|
let b = ord(s[i+1])
|
||||||
|
result.add cb64[a shr 2]
|
||||||
|
result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)]
|
||||||
|
result.add cb64[((b and 0x0F) shl 2)]
|
||||||
|
elif i < s.len:
|
||||||
|
let a = ord(s[i])
|
||||||
|
result.add cb64[a shr 2]
|
||||||
|
result.add cb64[(a and 3) shl 4]
|
||||||
|
|
||||||
|
proc toBase64a(u: TUid): string = toBase64a(cast[cstring](u), sizeof(u))
|
||||||
|
|
||||||
|
proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
|
||||||
|
|
||||||
|
proc hashSym(c: var MD5Context, s: PSym) =
|
||||||
|
if sfAnon in s.flags or s.kind == skGenericParam:
|
||||||
|
c &= ":anon"
|
||||||
|
else:
|
||||||
|
var it = s.owner
|
||||||
|
while it != nil:
|
||||||
|
hashSym(c, it)
|
||||||
|
c &= "."
|
||||||
|
it = s.owner
|
||||||
|
c &= s.name.s
|
||||||
|
|
||||||
|
proc hashTree(c: var MD5Context, n: PNode) =
|
||||||
|
if n == nil:
|
||||||
|
c &= "null"
|
||||||
|
return
|
||||||
|
var k = n.kind
|
||||||
|
md5Update(c, cast[cstring](addr(k)), 1)
|
||||||
|
# we really must not hash line information. 'n.typ' is debatable but
|
||||||
|
# shouldn't be necessary for now and avoids potential infinite recursions.
|
||||||
|
case n.kind
|
||||||
|
of nkEmpty, nkNilLit, nkType: discard
|
||||||
|
of nkIdent:
|
||||||
|
c &= n.ident.s
|
||||||
|
of nkSym:
|
||||||
|
hashSym(c, n.sym)
|
||||||
|
of nkCharLit..nkUInt64Lit:
|
||||||
|
var v = n.intVal
|
||||||
|
md5Update(c, cast[cstring](addr(v)), sizeof(v))
|
||||||
|
of nkFloatLit..nkFloat64Lit:
|
||||||
|
var v = n.floatVal
|
||||||
|
md5Update(c, cast[cstring](addr(v)), sizeof(v))
|
||||||
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
c &= n.strVal
|
||||||
|
else:
|
||||||
|
for i in 0.. <n.len: hashTree(c, n.sons[i])
|
||||||
|
|
||||||
|
const
|
||||||
|
typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
|
||||||
|
"Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
|
||||||
|
"GenericInvokation", "GenericBody", "GenericInst", "GenericParam",
|
||||||
|
"distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
|
||||||
|
"set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
|
||||||
|
"pointer", "OpenArray[$1]", "string", "CString", "Forward",
|
||||||
|
"int", "int8", "int16", "int32", "int64",
|
||||||
|
"float", "float32", "float64", "float128",
|
||||||
|
"uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
"bignum", "const ",
|
||||||
|
"!", "varargs[$1]", "iter[$1]", "Error Type",
|
||||||
|
"BuiltInTypeClass", "UserTypeClass",
|
||||||
|
"UserTypeClassInst", "CompositeTypeClass",
|
||||||
|
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
|
||||||
|
|
||||||
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
|
var t = typ
|
||||||
|
result = ""
|
||||||
|
if t == nil: return
|
||||||
|
if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags:
|
||||||
|
if t.kind == tyInt and isIntLit(t):
|
||||||
|
return t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||||
|
return t.sym.name.s
|
||||||
|
case t.kind
|
||||||
|
of tyInt:
|
||||||
|
if not isIntLit(t) or prefer == preferExported:
|
||||||
|
result = typeToStr[t.kind]
|
||||||
|
else:
|
||||||
|
result = "int literal(" & $t.n.intVal & ")"
|
||||||
|
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
||||||
|
result = typeToString(t.sons[0]) & '['
|
||||||
|
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
|
||||||
|
if i > 1: add(result, ", ")
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
add(result, ']')
|
||||||
|
of tyTypeDesc:
|
||||||
|
if t.base.kind == tyNone: result = "typedesc"
|
||||||
|
else: result = "typedesc[" & typeToString(t.base) & "]"
|
||||||
|
of tyStatic:
|
||||||
|
internalAssert t.len > 0
|
||||||
|
result = "static[" & typeToString(t.sons[0]) & "]"
|
||||||
|
of tyUserTypeClass:
|
||||||
|
internalAssert t.sym != nil and t.sym.owner != nil
|
||||||
|
return t.sym.owner.name.s
|
||||||
|
of tyBuiltInTypeClass:
|
||||||
|
result = case t.base.kind:
|
||||||
|
of tyVar: "var"
|
||||||
|
of tyRef: "ref"
|
||||||
|
of tyPtr: "ptr"
|
||||||
|
of tySequence: "seq"
|
||||||
|
of tyArray: "array"
|
||||||
|
of tySet: "set"
|
||||||
|
of tyRange: "range"
|
||||||
|
of tyDistinct: "distinct"
|
||||||
|
of tyProc: "proc"
|
||||||
|
of tyObject: "object"
|
||||||
|
of tyTuple: "tuple"
|
||||||
|
else: (internalAssert(false); "")
|
||||||
|
of tyUserTypeClassInst:
|
||||||
|
let body = t.base
|
||||||
|
result = body.sym.name.s & "["
|
||||||
|
for i in countup(1, sonsLen(t) - 2):
|
||||||
|
if i > 1: add(result, ", ")
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
result.add "]"
|
||||||
|
of tyAnd:
|
||||||
|
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
||||||
|
of tyOr:
|
||||||
|
result = typeToString(t.sons[0]) & " or " & typeToString(t.sons[1])
|
||||||
|
of tyNot:
|
||||||
|
result = "not " & typeToString(t.sons[0])
|
||||||
|
of tyExpr:
|
||||||
|
internalAssert t.len == 0
|
||||||
|
result = "expr"
|
||||||
|
of tyFromExpr, tyFieldAccessor:
|
||||||
|
result = renderTree(t.n)
|
||||||
|
of tyArray:
|
||||||
|
if t.sons[0].kind == tyRange:
|
||||||
|
result = "array[" & hashTree(t.sons[0].n) & ", " &
|
||||||
|
typeToString(t.sons[1]) & ']'
|
||||||
|
else:
|
||||||
|
result = "array[" & typeToString(t.sons[0]) & ", " &
|
||||||
|
typeToString(t.sons[1]) & ']'
|
||||||
|
of tyArrayConstr:
|
||||||
|
result = "Array constructor[" & hashTree(t.sons[0].n) & ", " &
|
||||||
|
typeToString(t.sons[1]) & ']'
|
||||||
|
of tySequence:
|
||||||
|
result = "seq[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyOrdinal:
|
||||||
|
result = "ordinal[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tySet:
|
||||||
|
result = "set[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyOpenArray:
|
||||||
|
result = "openarray[" & typeToString(t.sons[0]) & ']'
|
||||||
|
of tyDistinct:
|
||||||
|
result = "distinct " & typeToString(t.sons[0], preferName)
|
||||||
|
of tyTuple:
|
||||||
|
# we iterate over t.sons here, because t.n may be nil
|
||||||
|
result = "tuple["
|
||||||
|
if t.n != nil:
|
||||||
|
assert(sonsLen(t.n) == sonsLen(t))
|
||||||
|
for i in countup(0, sonsLen(t.n) - 1):
|
||||||
|
assert(t.n.sons[i].kind == nkSym)
|
||||||
|
add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t.n) - 1: add(result, ", ")
|
||||||
|
else:
|
||||||
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
|
add(result, ']')
|
||||||
|
of tyPtr, tyRef, tyVar, tyMutable, tyConst:
|
||||||
|
result = typeToStr[t.kind] & typeToString(t.sons[0])
|
||||||
|
of tyRange:
|
||||||
|
result = "range " & hashTree(t.n)
|
||||||
|
if prefer != preferExported:
|
||||||
|
result.add("(" & typeToString(t.sons[0]) & ")")
|
||||||
|
of tyProc:
|
||||||
|
result = if tfIterator in t.flags: "iterator (" else: "proc ("
|
||||||
|
for i in countup(1, sonsLen(t) - 1):
|
||||||
|
add(result, typeToString(t.sons[i]))
|
||||||
|
if i < sonsLen(t) - 1: add(result, ", ")
|
||||||
|
add(result, ')')
|
||||||
|
if t.sons[0] != nil: add(result, ": " & typeToString(t.sons[0]))
|
||||||
|
var prag: string
|
||||||
|
if t.callConv != ccDefault: prag = CallingConvToStr[t.callConv]
|
||||||
|
else: prag = ""
|
||||||
|
if tfNoSideEffect in t.flags:
|
||||||
|
addSep(prag)
|
||||||
|
add(prag, "noSideEffect")
|
||||||
|
if tfThread in t.flags:
|
||||||
|
addSep(prag)
|
||||||
|
add(prag, "thread")
|
||||||
|
if len(prag) != 0: add(result, "{." & prag & ".}")
|
||||||
|
of tyVarargs, tyIter:
|
||||||
|
result = typeToStr[t.kind] % typeToString(t.sons[0])
|
||||||
|
else:
|
||||||
|
result = typeToStr[t.kind]
|
||||||
|
if tfShared in t.flags: result = "shared " & result
|
||||||
|
if tfNotNil in t.flags: result.add(" not nil")
|
||||||
|
|
||||||
|
|
||||||
|
proc createDb() =
|
||||||
|
db.exec(sql"""
|
||||||
|
create table if not exists Module(
|
||||||
|
id integer primary key,
|
||||||
|
name varchar(256) not null,
|
||||||
|
fullpath varchar(256) not null,
|
||||||
|
interfHash varchar(256) not null,
|
||||||
|
fullHash varchar(256) not null,
|
||||||
|
|
||||||
|
created timestamp not null default (DATETIME('now')),
|
||||||
|
);""")
|
||||||
|
|
||||||
|
db.exec(sql"""
|
||||||
|
create table if not exists Symbol(
|
||||||
|
id integer primary key,
|
||||||
|
module integer not null,
|
||||||
|
name varchar(max) not null,
|
||||||
|
data varchar(max) not null,
|
||||||
|
created timestamp not null default (DATETIME('now')),
|
||||||
|
|
||||||
|
foreign key (module) references module(id)
|
||||||
|
);""")
|
||||||
|
|
||||||
|
db.exec(sql"""
|
||||||
|
create table if not exists Type(
|
||||||
|
id integer primary key,
|
||||||
|
module integer not null,
|
||||||
|
name varchar(max) not null,
|
||||||
|
data varchar(max) not null,
|
||||||
|
created timestamp not null default (DATETIME('now')),
|
||||||
|
|
||||||
|
foreign key (module) references module(id)
|
||||||
|
);""")
|
||||||
|
|
||||||
|
|
||||||
|
#db.exec(sql"""
|
||||||
|
# --create unique index if not exists TsstNameIx on TestResult(name);
|
||||||
|
# """, [])
|
||||||
|
|
||||||
|
|
@ -1915,7 +1915,6 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
internalError(n.info, "expr: proc not init " & sym.name.s)
|
internalError(n.info, "expr: proc not init " & sym.name.s)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
of nkClosure: genClosure(p, n, d)
|
of nkClosure: genClosure(p, n, d)
|
||||||
of nkMetaNode: expr(p, n.sons[0], d)
|
|
||||||
|
|
||||||
of nkEmpty: discard
|
of nkEmpty: discard
|
||||||
of nkWhileStmt: genWhileStmt(p, n)
|
of nkWhileStmt: genWhileStmt(p, n)
|
||||||
|
|
|
||||||
|
|
@ -1600,7 +1600,6 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
if lfNoDecl in s.loc.flags or s.magic != mNone: discard
|
if lfNoDecl in s.loc.flags or s.magic != mNone: discard
|
||||||
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
elif not p.g.generatedSyms.containsOrIncl(s.id):
|
||||||
app(p.locals, genProc(p, s))
|
app(p.locals, genProc(p, s))
|
||||||
of nkMetaNode: gen(p, n.sons[0], r)
|
|
||||||
of nkType: r.res = genTypeInfo(p, n.typ)
|
of nkType: r.res = genTypeInfo(p, n.typ)
|
||||||
of nkStmtList, nkStmtListExpr:
|
of nkStmtList, nkStmtListExpr:
|
||||||
# this shows the distinction is nice for backends and should be kept
|
# this shows the distinction is nice for backends and should be kept
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ type
|
||||||
errAmbiguousCallXYZ, errWrongNumberOfArguments,
|
errAmbiguousCallXYZ, errWrongNumberOfArguments,
|
||||||
errXCannotBePassedToProcVar,
|
errXCannotBePassedToProcVar,
|
||||||
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
||||||
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue,
|
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX,
|
||||||
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
|
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
|
||||||
errInvalidOrderInArrayConstructor,
|
errInvalidOrderInArrayConstructor,
|
||||||
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
|
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
|
||||||
|
|
@ -266,7 +266,7 @@ const
|
||||||
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
|
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
|
||||||
errImplOfXexpected: "implementation of \'$1\' expected",
|
errImplOfXexpected: "implementation of \'$1\' expected",
|
||||||
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
||||||
errDiscardValue: "value returned by statement has to be discarded",
|
errDiscardValueX: "value of type '$1' has to be discarded",
|
||||||
errInvalidDiscard: "statement returns no value that can be discarded",
|
errInvalidDiscard: "statement returns no value that can be discarded",
|
||||||
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
|
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
|
||||||
errCannotBindXTwice: "cannot bind parameter \'$1\' twice",
|
errCannotBindXTwice: "cannot bind parameter \'$1\' twice",
|
||||||
|
|
|
||||||
|
|
@ -1268,7 +1268,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
put(g, tkBracketLe, "[")
|
put(g, tkBracketLe, "[")
|
||||||
gcomma(g, n)
|
gcomma(g, n)
|
||||||
put(g, tkBracketRi, "]")
|
put(g, tkBracketRi, "]")
|
||||||
of nkMetaNode:
|
of nkMetaNode_Obsolete:
|
||||||
put(g, tkParLe, "(META|")
|
put(g, tkParLe, "(META|")
|
||||||
gsub(g, n.sons[0])
|
gsub(g, n.sons[0])
|
||||||
put(g, tkParRi, ")")
|
put(g, tkParRi, ")")
|
||||||
|
|
|
||||||
|
|
@ -890,7 +890,7 @@ proc loadStub*(s: PSym) =
|
||||||
|
|
||||||
# deactivate the GC here because we do a deep recursion and generate no
|
# deactivate the GC here because we do a deep recursion and generate no
|
||||||
# garbage when restoring parts of the object graph anyway.
|
# garbage when restoring parts of the object graph anyway.
|
||||||
# Since we die with internal errors if this fails, so no try-finally is
|
# Since we die with internal errors if this fails, no try-finally is
|
||||||
# necessary.
|
# necessary.
|
||||||
GC_disable()
|
GC_disable()
|
||||||
rawLoadStub(s)
|
rawLoadStub(s)
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
result = fixupTypeAfterEval(c, result, e)
|
result = fixupTypeAfterEval(c, result, e)
|
||||||
except:
|
except ERecoverableError:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -641,9 +641,11 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||||
result = evalStaticExpr(c.module, call, c.p.owner)
|
result = evalStaticExpr(c.module, call, c.p.owner)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
localError(n.info, errCannotInterpretNodeX, renderTree(call))
|
localError(n.info, errCannotInterpretNodeX, renderTree(call))
|
||||||
|
else: result = fixupTypeAfterEval(c, result, n)
|
||||||
else:
|
else:
|
||||||
result = evalConstExpr(c.module, call)
|
result = evalConstExpr(c.module, call)
|
||||||
if result.isNil: result = n
|
if result.isNil: result = n
|
||||||
|
else: result = fixupTypeAfterEval(c, result, n)
|
||||||
#if result != n:
|
#if result != n:
|
||||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||||
|
|
||||||
|
|
@ -653,6 +655,8 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
localError(n.info, errCannotInterpretNodeX, renderTree(n))
|
localError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||||
result = emptyNode
|
result = emptyNode
|
||||||
|
else:
|
||||||
|
result = fixupTypeAfterEval(c, result, a)
|
||||||
|
|
||||||
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
|
|
|
||||||
|
|
@ -537,7 +537,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||||
else:
|
else:
|
||||||
localError(n.info, errIndexOutOfBounds)
|
localError(n.info, errIndexOutOfBounds)
|
||||||
of nkBracket, nkMetaNode:
|
of nkBracket:
|
||||||
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
|
if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)]
|
||||||
else: localError(n.info, errIndexOutOfBounds)
|
else: localError(n.info, errIndexOutOfBounds)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ proc implicitlyDiscardable(n: PNode): bool =
|
||||||
proc fixNilType(n: PNode) =
|
proc fixNilType(n: PNode) =
|
||||||
if isAtom(n):
|
if isAtom(n):
|
||||||
if n.kind != nkNilLit and n.typ != nil:
|
if n.kind != nkNilLit and n.typ != nil:
|
||||||
localError(n.info, errDiscardValue)
|
localError(n.info, errDiscardValueX, n.typ.typeToString)
|
||||||
elif n.kind in {nkStmtList, nkStmtListExpr}:
|
elif n.kind in {nkStmtList, nkStmtListExpr}:
|
||||||
n.kind = nkStmtList
|
n.kind = nkStmtList
|
||||||
for it in n: fixNilType(it)
|
for it in n: fixNilType(it)
|
||||||
|
|
@ -155,7 +155,7 @@ proc discardCheck(c: PContext, result: PNode) =
|
||||||
else:
|
else:
|
||||||
var n = result
|
var n = result
|
||||||
while n.kind in skipForDiscardable: n = n.lastSon
|
while n.kind in skipForDiscardable: n = n.lastSon
|
||||||
localError(n.info, errDiscardValue)
|
localError(n.info, errDiscardValueX, result.typ.typeToString)
|
||||||
|
|
||||||
proc semIf(c: PContext, n: PNode): PNode =
|
proc semIf(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -332,6 +332,7 @@ proc checkNilable(v: PSym) =
|
||||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
var b: PNode
|
var b: PNode
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
|
var hasCompileTime = false
|
||||||
for i in countup(0, sonsLen(n)-1):
|
for i in countup(0, sonsLen(n)-1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||||
|
|
@ -411,6 +412,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
v.typ = tup.sons[j]
|
v.typ = tup.sons[j]
|
||||||
b.sons[j] = newSymNode(v)
|
b.sons[j] = newSymNode(v)
|
||||||
checkNilable(v)
|
checkNilable(v)
|
||||||
|
if sfCompileTime in v.flags: hasCompileTime = true
|
||||||
|
if hasCompileTime: vm.setupCompileTimeVar(c.module, result)
|
||||||
|
|
||||||
proc semConst(c: PContext, n: PNode): PNode =
|
proc semConst(c: PContext, n: PNode): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
|
|
|
||||||
|
|
@ -463,7 +463,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
of tyAnd:
|
of tyAnd:
|
||||||
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
||||||
of tyOr:
|
of tyOr:
|
||||||
result = typeToString(t.sons[0]) & " and " & typeToString(t.sons[1])
|
result = typeToString(t.sons[0]) & " or " & typeToString(t.sons[1])
|
||||||
of tyNot:
|
of tyNot:
|
||||||
result = "not " & typeToString(t.sons[0])
|
result = "not " & typeToString(t.sons[0])
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
|
|
|
||||||
981
compiler/vm.nim
981
compiler/vm.nim
File diff suppressed because it is too large
Load diff
|
|
@ -8,7 +8,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module contains the type definitions for the new evaluation engine.
|
## This module contains the type definitions for the new evaluation engine.
|
||||||
## An instruction is 1-2 int32s in memory, it is a register based VM.
|
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
||||||
|
|
||||||
import ast, passes, msgs, intsets
|
import ast, passes, msgs, intsets
|
||||||
|
|
||||||
|
|
@ -32,17 +32,17 @@ type
|
||||||
opcAsgnFloat,
|
opcAsgnFloat,
|
||||||
opcAsgnRef,
|
opcAsgnRef,
|
||||||
opcAsgnComplex,
|
opcAsgnComplex,
|
||||||
|
opcRegToNode,
|
||||||
|
opcNodeToReg,
|
||||||
|
|
||||||
opcLdArr, # a = b[c]
|
opcLdArr, # a = b[c]
|
||||||
opcLdArrRef,
|
|
||||||
opcWrArr, # a[b] = c
|
opcWrArr, # a[b] = c
|
||||||
opcWrArrRef,
|
|
||||||
opcLdObj, # a = b.c
|
opcLdObj, # a = b.c
|
||||||
opcLdObjRef,
|
|
||||||
opcWrObj, # a.b = c
|
opcWrObj, # a.b = c
|
||||||
opcWrObjRef,
|
opcAddrReg,
|
||||||
opcAddr,
|
opcAddrNode,
|
||||||
opcDeref,
|
opcLdDeref,
|
||||||
|
opcWrDeref,
|
||||||
opcWrStrIdx,
|
opcWrStrIdx,
|
||||||
opcLdStrIdx, # a = b[c]
|
opcLdStrIdx, # a = b[c]
|
||||||
|
|
||||||
|
|
@ -117,15 +117,13 @@ type
|
||||||
opcNew,
|
opcNew,
|
||||||
opcNewSeq,
|
opcNewSeq,
|
||||||
opcLdNull, # dest = nullvalue(types[Bx])
|
opcLdNull, # dest = nullvalue(types[Bx])
|
||||||
|
opcLdNullReg,
|
||||||
opcLdConst, # dest = constants[Bx]
|
opcLdConst, # dest = constants[Bx]
|
||||||
opcAsgnConst, # dest = copy(constants[Bx])
|
opcAsgnConst, # dest = copy(constants[Bx])
|
||||||
opcLdGlobal, # dest = globals[Bx]
|
opcLdGlobal, # dest = globals[Bx]
|
||||||
|
|
||||||
opcLdImmInt, # dest = immediate value
|
opcLdImmInt, # dest = immediate value
|
||||||
opcNBindSym,
|
opcNBindSym,
|
||||||
opcWrGlobal,
|
|
||||||
opcWrGlobalRef,
|
|
||||||
opcGlobalAlias, # load an alias to a global into a register
|
|
||||||
opcGlobalOnce, # used to introduce an assignment to a global once
|
|
||||||
opcSetType, # dest.typ = types[Bx]
|
opcSetType, # dest.typ = types[Bx]
|
||||||
opcTypeTrait
|
opcTypeTrait
|
||||||
|
|
||||||
|
|
@ -165,8 +163,6 @@ type
|
||||||
blocks*: seq[TBlock] # blocks; temp data structure
|
blocks*: seq[TBlock] # blocks; temp data structure
|
||||||
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
|
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
|
||||||
maxSlots*: int
|
maxSlots*: int
|
||||||
globals*: array[TRegister, int] # hack: to support passing globals byref
|
|
||||||
# we map a slot persistently to a global
|
|
||||||
|
|
||||||
PCtx* = ref TCtx
|
PCtx* = ref TCtx
|
||||||
TCtx* = object of passes.TPassContext # code gen context
|
TCtx* = object of passes.TPassContext # code gen context
|
||||||
|
|
@ -183,6 +179,7 @@ type
|
||||||
callsite*: PNode
|
callsite*: PNode
|
||||||
mode*: TEvalMode
|
mode*: TEvalMode
|
||||||
features*: TSandboxFlags
|
features*: TSandboxFlags
|
||||||
|
traceActive*: bool
|
||||||
|
|
||||||
TPosition* = distinct int
|
TPosition* = distinct int
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -139,25 +139,12 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
|
||||||
if not c.slots[i].inUse:
|
if not c.slots[i].inUse:
|
||||||
c.slots[i] = (inUse: true, kind: k)
|
c.slots[i] = (inUse: true, kind: k)
|
||||||
return TRegister(i)
|
return TRegister(i)
|
||||||
|
if c.maxSlots >= high(TRegister):
|
||||||
|
internalError("cannot generate code; too many registers required")
|
||||||
result = TRegister(c.maxSlots)
|
result = TRegister(c.maxSlots)
|
||||||
c.slots[c.maxSlots] = (inUse: true, kind: k)
|
c.slots[c.maxSlots] = (inUse: true, kind: k)
|
||||||
inc c.maxSlots
|
inc c.maxSlots
|
||||||
|
|
||||||
proc getGlobalSlot(c: PCtx; n: PNode; s: PSym): TRegister =
|
|
||||||
let p = c.prc
|
|
||||||
for i in 0 .. p.maxSlots-1:
|
|
||||||
if p.globals[i] == s.id: return TRegister(i)
|
|
||||||
|
|
||||||
result = TRegister(p.maxSlots)
|
|
||||||
p.slots[p.maxSlots] = (inUse: true, kind: slotFixedVar)
|
|
||||||
p.globals[p.maxSlots] = s.id
|
|
||||||
inc p.maxSlots
|
|
||||||
# XXX this is still not correct! We need to load the global in a proc init
|
|
||||||
# section, otherwise control flow could lead to a usage before it's been
|
|
||||||
# loaded.
|
|
||||||
c.gABx(n, opcGlobalAlias, result, s.position)
|
|
||||||
# XXX add some internal asserts here
|
|
||||||
|
|
||||||
proc freeTemp(c: PCtx; r: TRegister) =
|
proc freeTemp(c: PCtx; r: TRegister) =
|
||||||
let c = c.prc
|
let c = c.prc
|
||||||
if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false
|
if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false
|
||||||
|
|
@ -322,12 +309,6 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
|
||||||
c.patch(L1)
|
c.patch(L1)
|
||||||
|
|
||||||
proc nilLiteral(n: PNode): PNode =
|
proc nilLiteral(n: PNode): PNode =
|
||||||
if n.kind == nkNilLit and n.typ.sym != nil and
|
|
||||||
n.typ.sym.magic == mPNimrodNode:
|
|
||||||
let nilo = newNodeIT(nkNilLit, n.info, n.typ)
|
|
||||||
result = newNodeIT(nkMetaNode, n.info, n.typ)
|
|
||||||
result.add nilo
|
|
||||||
else:
|
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc rawGenLiteral(c: PCtx; n: PNode): int =
|
proc rawGenLiteral(c: PCtx; n: PNode): int =
|
||||||
|
|
@ -470,21 +451,37 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.gABC(n, opcIndCallAsgn, dest, x, n.len)
|
c.gABC(n, opcIndCallAsgn, dest, x, n.len)
|
||||||
c.freeTempRange(x, n.len)
|
c.freeTempRange(x, n.len)
|
||||||
|
|
||||||
|
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
|
||||||
|
|
||||||
proc needsAsgnPatch(n: PNode): bool =
|
proc needsAsgnPatch(n: PNode): bool =
|
||||||
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}
|
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
||||||
|
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
||||||
|
|
||||||
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
let dest = c.genx(le.sons[0])
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(le.sons[1])
|
let idx = c.genx(le.sons[1])
|
||||||
c.gABC(le, opcWrArrRef, dest, idx, value)
|
c.gABC(le, opcWrArr, dest, idx, value)
|
||||||
|
c.freeTemp(dest)
|
||||||
|
c.freeTemp(idx)
|
||||||
of nkDotExpr, nkCheckedFieldExpr:
|
of nkDotExpr, nkCheckedFieldExpr:
|
||||||
# XXX field checks here
|
# XXX field checks here
|
||||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||||
let dest = c.genx(left.sons[0])
|
let dest = c.genx(left.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(left.sons[1])
|
let idx = c.genx(left.sons[1])
|
||||||
c.gABC(left, opcWrObjRef, dest, idx, value)
|
c.gABC(left, opcWrObj, dest, idx, value)
|
||||||
|
c.freeTemp(dest)
|
||||||
|
c.freeTemp(idx)
|
||||||
|
of nkDerefExpr, nkHiddenDeref:
|
||||||
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
|
c.gABC(le, opcWrDeref, dest, value)
|
||||||
|
c.freeTemp(dest)
|
||||||
|
of nkSym:
|
||||||
|
if le.sym.isGlobal:
|
||||||
|
let dest = c.genx(le, {gfAddrOf})
|
||||||
|
c.gABC(le, opcWrDeref, dest, value)
|
||||||
|
c.freeTemp(dest)
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
@ -594,10 +591,10 @@ proc genAddSubInt(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||||
|
|
||||||
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
proc genConv(c: PCtx; n, arg: PNode; dest: var TDest; opc=opcConv) =
|
||||||
let tmp = c.genx(arg)
|
let tmp = c.genx(arg)
|
||||||
c.gABx(n, opcSetType, tmp, genType(c, arg.typ))
|
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opc, dest, tmp)
|
c.gABC(n, opc, dest, tmp)
|
||||||
c.gABx(n, opc, 0, genType(c, n.typ))
|
c.gABx(n, opc, 0, genType(c, n.typ))
|
||||||
|
c.gABx(n, opc, 0, genType(c, arg.typ))
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
proc genCard(c: PCtx; n: PNode; dest: var TDest) =
|
proc genCard(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
|
|
@ -623,6 +620,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.genAddSubInt(n, dest, opcAddInt)
|
c.genAddSubInt(n, dest, opcAddInt)
|
||||||
of mInc, mDec:
|
of mInc, mDec:
|
||||||
unused(n, dest)
|
unused(n, dest)
|
||||||
|
# XXX generates inefficient code for globals
|
||||||
var d = c.genx(n.sons[1]).TDest
|
var d = c.genx(n.sons[1]).TDest
|
||||||
c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
|
c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
|
||||||
c.genAsgnPatch(n.sons[1], d)
|
c.genAsgnPatch(n.sons[1], d)
|
||||||
|
|
@ -636,6 +634,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.genNewSeq(n)
|
c.genNewSeq(n)
|
||||||
of mNewString:
|
of mNewString:
|
||||||
genUnaryABC(c, n, dest, opcNewStr)
|
genUnaryABC(c, n, dest, opcNewStr)
|
||||||
|
# XXX buggy
|
||||||
of mNewStringOfCap:
|
of mNewStringOfCap:
|
||||||
# we ignore the 'cap' argument and translate it as 'newString(0)'.
|
# we ignore the 'cap' argument and translate it as 'newString(0)'.
|
||||||
# eval n.sons[1] for possible side effects:
|
# eval n.sons[1] for possible side effects:
|
||||||
|
|
@ -644,6 +643,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, opcNewStr, dest, tmp)
|
c.gABC(n, opcNewStr, dest, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
# XXX buggy
|
||||||
of mLengthOpenArray, mLengthArray, mLengthSeq:
|
of mLengthOpenArray, mLengthArray, mLengthSeq:
|
||||||
genUnaryABI(c, n, dest, opcLenSeq)
|
genUnaryABI(c, n, dest, opcLenSeq)
|
||||||
of mLengthStr:
|
of mLengthStr:
|
||||||
|
|
@ -905,6 +905,10 @@ const
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
||||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
|
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
|
||||||
|
|
||||||
|
proc fitsRegister*(t: PType): bool =
|
||||||
|
t.skipTypes(abstractInst-{tyTypeDesc}).kind in {
|
||||||
|
tyRange, tyEnum, tyBool, tyInt..tyUInt64}
|
||||||
|
|
||||||
proc requiresCopy(n: PNode): bool =
|
proc requiresCopy(n: PNode): bool =
|
||||||
if n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind in atomicTypes:
|
if n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind in atomicTypes:
|
||||||
result = false
|
result = false
|
||||||
|
|
@ -919,7 +923,8 @@ proc unneededIndirection(n: PNode): bool =
|
||||||
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
flags: TGenFlags) =
|
flags: TGenFlags) =
|
||||||
# a nop for certain types
|
# a nop for certain types
|
||||||
let flags = if opc == opcAddr: flags+{gfAddrOf} else: flags
|
let isAddr = opc in {opcAddrNode, opcAddrReg}
|
||||||
|
let flags = if isAddr: flags+{gfAddrOf} else: flags
|
||||||
# consider:
|
# consider:
|
||||||
# proc foo(f: var ref int) =
|
# proc foo(f: var ref int) =
|
||||||
# f = new(int)
|
# f = new(int)
|
||||||
|
|
@ -929,12 +934,17 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
#
|
#
|
||||||
# The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for
|
# The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for
|
||||||
# nkAddr we must not use 'unneededIndirection', but for deref we use it.
|
# nkAddr we must not use 'unneededIndirection', but for deref we use it.
|
||||||
if opc != opcAddr and unneededIndirection(n.sons[0]):
|
if not isAddr and unneededIndirection(n.sons[0]):
|
||||||
gen(c, n.sons[0], dest, flags)
|
gen(c, n.sons[0], dest, flags)
|
||||||
else:
|
else:
|
||||||
let tmp = c.genx(n.sons[0], flags)
|
let tmp = c.genx(n.sons[0], flags)
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
|
if not isAddr:
|
||||||
gABC(c, n, opc, dest, tmp)
|
gABC(c, n, opc, dest, tmp)
|
||||||
|
elif c.prc.slots[tmp].kind >= slotTempUnknown:
|
||||||
|
gABC(c, n, opcAddrReg, dest, tmp)
|
||||||
|
else:
|
||||||
|
gABC(c, n, opcAddrNode, dest, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
proc whichAsgnOpc(n: PNode): TOpcode =
|
proc whichAsgnOpc(n: PNode): TOpcode =
|
||||||
|
|
@ -952,8 +962,7 @@ proc whichAsgnOpc(n: PNode): TOpcode =
|
||||||
|
|
||||||
proc isRef(t: PType): bool = t.skipTypes(abstractRange-{tyTypeDesc}).kind == tyRef
|
proc isRef(t: PType): bool = t.skipTypes(abstractRange-{tyTypeDesc}).kind == tyRef
|
||||||
|
|
||||||
proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode =
|
proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc
|
||||||
if isRef(n.typ): succ(opc) else: opc
|
|
||||||
|
|
||||||
proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
|
proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
|
|
@ -961,8 +970,6 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
|
||||||
gABC(c, ri, whichAsgnOpc(ri), dest, tmp)
|
gABC(c, ri, whichAsgnOpc(ri), dest, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
|
|
||||||
|
|
||||||
proc setSlot(c: PCtx; v: PSym) =
|
proc setSlot(c: PCtx; v: PSym) =
|
||||||
# XXX generate type initialization here?
|
# XXX generate type initialization here?
|
||||||
if v.position == 0:
|
if v.position == 0:
|
||||||
|
|
@ -974,29 +981,36 @@ proc setSlot(c: PCtx; v: PSym) =
|
||||||
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
let dest = c.genx(le.sons[0])
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(le.sons[1])
|
let idx = c.genx(le.sons[1])
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
||||||
tyString, tyCString}:
|
tyString, tyCString}:
|
||||||
c.gABC(le, opcWrStrIdx, dest, idx, tmp)
|
c.gABC(le, opcWrStrIdx, dest, idx, tmp)
|
||||||
else:
|
else:
|
||||||
c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
|
c.gABC(le, opcWrArr, dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkDotExpr, nkCheckedFieldExpr:
|
of nkDotExpr, nkCheckedFieldExpr:
|
||||||
# XXX field checks here
|
# XXX field checks here
|
||||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||||
let dest = c.genx(left.sons[0])
|
let dest = c.genx(left.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(left.sons[1])
|
let idx = c.genx(left.sons[1])
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
c.gABC(left, whichAsgnOpc(left, opcWrObj), dest, idx, tmp)
|
c.gABC(left, opcWrObj, dest, idx, tmp)
|
||||||
|
c.freeTemp(tmp)
|
||||||
|
of nkDerefExpr, nkHiddenDeref:
|
||||||
|
let dest = c.genx(le, {gfAddrOf})
|
||||||
|
let tmp = c.genx(ri)
|
||||||
|
c.gABC(le, opcWrDeref, dest, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let s = le.sym
|
let s = le.sym
|
||||||
if s.isGlobal:
|
if s.isGlobal:
|
||||||
withTemp(tmp, le.typ):
|
withTemp(tmp, le.typ):
|
||||||
gen(c, ri, tmp)
|
c.gen(le, tmp, {gfAddrOf})
|
||||||
c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
|
let val = c.genx(ri)
|
||||||
|
c.gABC(le, opcWrDeref, tmp, val)
|
||||||
|
c.freeTemp(val)
|
||||||
else:
|
else:
|
||||||
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
||||||
internalAssert s.position > 0 or (s.position == 0 and
|
internalAssert s.position > 0 or (s.position == 0 and
|
||||||
|
|
@ -1004,7 +1018,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
var dest: TRegister = s.position + ord(s.kind == skParam)
|
var dest: TRegister = s.position + ord(s.kind == skParam)
|
||||||
gen(c, ri, dest)
|
gen(c, ri, dest)
|
||||||
else:
|
else:
|
||||||
let dest = c.genx(le)
|
let dest = c.genx(le, {gfAddrOf})
|
||||||
genAsgn(c, dest, ri, requiresCopy)
|
genAsgn(c, dest, ri, requiresCopy)
|
||||||
|
|
||||||
proc genLit(c: PCtx; n: PNode; dest: var TDest) =
|
proc genLit(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
|
|
@ -1034,18 +1048,22 @@ proc cannotEval(n: PNode) {.noinline.} =
|
||||||
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
||||||
n.renderTree)
|
n.renderTree)
|
||||||
|
|
||||||
|
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
||||||
|
|
||||||
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
||||||
c.globals.add(emptyNode.copyNode)
|
c.globals.add(getNullValue(s.typ, n.info))
|
||||||
s.position = c.globals.len
|
s.position = c.globals.len
|
||||||
# This is rather hard to support, due to the laziness of the VM code
|
# This is rather hard to support, due to the laziness of the VM code
|
||||||
# generator. See tests/compile/tmacro2 for why this is necesary:
|
# generator. See tests/compile/tmacro2 for why this is necesary:
|
||||||
# var decls{.compileTime.}: seq[PNimrodNode] = @[]
|
# var decls{.compileTime.}: seq[PNimrodNode] = @[]
|
||||||
c.gABx(n, opcGlobalOnce, 0, s.position)
|
let dest = c.getTemp(s.typ)
|
||||||
|
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||||
let tmp = c.genx(s.ast)
|
let tmp = c.genx(s.ast)
|
||||||
c.gABx(n, whichAsgnOpc(n, opcWrGlobal), tmp, s.position)
|
c.gABC(n, opcWrDeref, dest, tmp)
|
||||||
|
c.freeTemp(dest)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if s.isGlobal:
|
if s.isGlobal:
|
||||||
if sfCompileTime in s.flags or c.mode == emRepl:
|
if sfCompileTime in s.flags or c.mode == emRepl:
|
||||||
|
|
@ -1055,9 +1073,12 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
if s.position == 0:
|
if s.position == 0:
|
||||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||||
else: genGlobalInit(c, n, s)
|
else: genGlobalInit(c, n, s)
|
||||||
if dest < 0:
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
dest = c.getGlobalSlot(n, s)
|
if gfAddrOf notin flags and fitsRegister(s.typ):
|
||||||
#c.gABx(n, opcAliasGlobal, dest, s.position)
|
var cc = c.getTemp(n.typ)
|
||||||
|
c.gABx(n, opcLdGlobal, cc, s.position)
|
||||||
|
c.gABC(n, opcNodeToReg, dest, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
else:
|
else:
|
||||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1078,7 +1099,13 @@ proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
let a = c.genx(n.sons[0], flags)
|
let a = c.genx(n.sons[0], flags)
|
||||||
let b = c.genx(n.sons[1], {})
|
let b = c.genx(n.sons[1], {})
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABC(n, (if gfAddrOf in flags: succ(opc) else: opc), dest, a, b)
|
if gfAddrOf notin flags and fitsRegister(n.typ):
|
||||||
|
var cc = c.getTemp(n.typ)
|
||||||
|
c.gABC(n, opc, cc, a, b)
|
||||||
|
c.gABC(n, opcNodeToReg, dest, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
|
else:
|
||||||
|
c.gABC(n, opc, dest, a, b)
|
||||||
c.freeTemp(a)
|
c.freeTemp(a)
|
||||||
c.freeTemp(b)
|
c.freeTemp(b)
|
||||||
|
|
||||||
|
|
@ -1096,7 +1123,6 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
else:
|
else:
|
||||||
genAccess(c, n, dest, opcLdArr, flags)
|
genAccess(c, n, dest, opcLdArr, flags)
|
||||||
|
|
||||||
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
|
||||||
proc getNullValueAux(obj: PNode, result: PNode) =
|
proc getNullValueAux(obj: PNode, result: PNode) =
|
||||||
case obj.kind
|
case obj.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
|
|
@ -1121,11 +1147,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkFloatLit, info, t)
|
result = newNodeIT(nkFloatLit, info, t)
|
||||||
of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
|
of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyStatic, tyRef:
|
tyStmt, tyTypeDesc, tyStatic, tyRef:
|
||||||
if t.sym != nil and t.sym.magic == mPNimrodNode:
|
|
||||||
let nilo = newNodeIT(nkNilLit, info, t)
|
|
||||||
result = newNodeIT(nkMetaNode, info, t)
|
|
||||||
result.add nilo
|
|
||||||
else:
|
|
||||||
result = newNodeIT(nkNilLit, info, t)
|
result = newNodeIT(nkNilLit, info, t)
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if t.callConv != ccClosure:
|
if t.callConv != ccClosure:
|
||||||
|
|
@ -1154,6 +1175,9 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkCurly, info, t)
|
result = newNodeIT(nkCurly, info, t)
|
||||||
else: internalError("getNullValue: " & $t.kind)
|
else: internalError("getNullValue: " & $t.kind)
|
||||||
|
|
||||||
|
proc ldNullOpcode(t: PType): TOpcode =
|
||||||
|
if fitsRegister(t): opcLdNullReg else: opcLdNull
|
||||||
|
|
||||||
proc genVarSection(c: PCtx; n: PNode) =
|
proc genVarSection(c: PCtx; n: PNode) =
|
||||||
for a in n:
|
for a in n:
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
|
|
@ -1164,8 +1188,8 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
setSlot(c, a[i].sym)
|
setSlot(c, a[i].sym)
|
||||||
# v = t[i]
|
# v = t[i]
|
||||||
var v: TDest = -1
|
var v: TDest = -1
|
||||||
genRdVar(c, a[i], v)
|
genRdVar(c, a[i], v, {gfAddrOf})
|
||||||
c.gABC(n, opcLdObj, v, tmp, i)
|
c.gABC(n, opcWrObj, v, tmp, i)
|
||||||
# XXX globals?
|
# XXX globals?
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
elif a.sons[0].kind == nkSym:
|
elif a.sons[0].kind == nkSym:
|
||||||
|
|
@ -1177,27 +1201,28 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
let sa = if s.ast.isNil: getNullValue(s.typ, a.info) else: s.ast
|
let sa = if s.ast.isNil: getNullValue(s.typ, a.info) else: s.ast
|
||||||
c.globals.add(sa)
|
c.globals.add(sa)
|
||||||
s.position = c.globals.len
|
s.position = c.globals.len
|
||||||
# "Once support" is unnecessary here
|
|
||||||
if a.sons[2].kind == nkEmpty:
|
if a.sons[2].kind == nkEmpty:
|
||||||
when false:
|
when false:
|
||||||
withTemp(tmp, s.typ):
|
withTemp(tmp, s.typ):
|
||||||
c.gABx(a, opcLdNull, tmp, c.genType(s.typ))
|
c.gABx(a, opcLdNull, tmp, c.genType(s.typ))
|
||||||
c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
|
c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
|
||||||
else:
|
else:
|
||||||
let tmp = genx(c, a.sons[2])
|
let tmp = c.genx(a.sons[0], {gfAddrOf})
|
||||||
c.gABx(a, whichAsgnOpc(a.sons[0], opcWrGlobal), tmp, s.position)
|
let val = c.genx(a.sons[2])
|
||||||
|
c.gABC(a, opcWrDeref, tmp, val)
|
||||||
|
c.freeTemp(val)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
else:
|
else:
|
||||||
setSlot(c, s)
|
setSlot(c, s)
|
||||||
if a.sons[2].kind == nkEmpty:
|
if a.sons[2].kind == nkEmpty:
|
||||||
c.gABx(a, opcLdNull, s.position, c.genType(s.typ))
|
c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
|
||||||
else:
|
else:
|
||||||
gen(c, a.sons[2], s.position.TRegister)
|
gen(c, a.sons[2], s.position.TRegister)
|
||||||
else:
|
else:
|
||||||
# assign to a.sons[0]; happens for closures
|
# assign to a.sons[0]; happens for closures
|
||||||
if a.sons[2].kind == nkEmpty:
|
if a.sons[2].kind == nkEmpty:
|
||||||
let tmp = genx(c, a.sons[0])
|
let tmp = genx(c, a.sons[0])
|
||||||
c.gABx(a, opcLdNull, tmp, c.genType(a.sons[0].typ))
|
c.gABx(a, ldNullOpcode(a[0].typ), tmp, c.genType(a.sons[0].typ))
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
else:
|
else:
|
||||||
genAsgn(c, a.sons[0], a.sons[2], true)
|
genAsgn(c, a.sons[0], a.sons[2], true)
|
||||||
|
|
@ -1205,10 +1230,19 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||||
if n.len > 0:
|
|
||||||
let intType = getSysType(tyInt)
|
let intType = getSysType(tyInt)
|
||||||
|
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
|
||||||
|
if seqType.kind == tySequence:
|
||||||
|
var tmp = c.getTemp(intType)
|
||||||
|
c.gABx(n, opcLdImmInt, tmp, n.len)
|
||||||
|
c.gABx(n, opcNewSeq, dest, c.genType(seqType))
|
||||||
|
c.gABx(n, opcNewSeq, tmp, 0)
|
||||||
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
|
if n.len > 0:
|
||||||
var tmp = getTemp(c, intType)
|
var tmp = getTemp(c, intType)
|
||||||
c.gABx(n, opcLdNull, tmp, c.genType(intType))
|
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
||||||
for x in n:
|
for x in n:
|
||||||
let a = c.genx(x)
|
let a = c.genx(x)
|
||||||
c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
|
c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
|
||||||
|
|
@ -1274,7 +1308,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
||||||
genRdVar(c, n, dest)
|
genRdVar(c, n, dest, flags)
|
||||||
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator:
|
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator:
|
||||||
# 'skTemplate' is only allowed for 'getAst' support:
|
# 'skTemplate' is only allowed for 'getAst' support:
|
||||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||||
|
|
@ -1320,8 +1354,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
||||||
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
|
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
|
||||||
of nkBracketExpr: genArrAccess(c, n, dest, flags)
|
of nkBracketExpr: genArrAccess(c, n, dest, flags)
|
||||||
of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref, flags)
|
of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcLdDeref, flags)
|
||||||
of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr, flags)
|
of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags)
|
||||||
of nkWhenStmt, nkIfStmt, nkIfExpr: genIf(c, n, dest)
|
of nkWhenStmt, nkIfStmt, nkIfExpr: genIf(c, n, dest)
|
||||||
of nkCaseStmt: genCase(c, n, dest)
|
of nkCaseStmt: genCase(c, n, dest)
|
||||||
of nkWhileStmt:
|
of nkWhileStmt:
|
||||||
|
|
@ -1506,7 +1540,7 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||||
c.gABC(body, opcEof, eofInstr.regA)
|
c.gABC(body, opcEof, eofInstr.regA)
|
||||||
c.optimizeJumps(result)
|
c.optimizeJumps(result)
|
||||||
s.offset = c.prc.maxSlots
|
s.offset = c.prc.maxSlots
|
||||||
#if s.name.s == "concatStyleInterpolation":
|
#if s.name.s == "importImpl_forward" or s.name.s == "importImpl":
|
||||||
# c.echoCode(result)
|
# c.echoCode(result)
|
||||||
# echo renderTree(body)
|
# echo renderTree(body)
|
||||||
c.prc = oldPrc
|
c.prc = oldPrc
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ macro okayy:stmt =
|
||||||
for node in decls: result.add node
|
for node in decls: result.add node
|
||||||
for node in impls: result.add node
|
for node in impls: result.add node
|
||||||
|
|
||||||
importimpl(Item, int):
|
importImpl(Item, int):
|
||||||
echo 42
|
echo 42
|
||||||
importImpl(Foo, int16):
|
importImpl(Foo, int16):
|
||||||
echo 77
|
echo 77
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,9 @@
|
||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
#
|
#
|
||||||
when defined(Linux):
|
|
||||||
const Lib = "libchipmunk.so.6.1.1"
|
const Lib = "libchipmunk.so.6.1.1"
|
||||||
else:
|
|
||||||
{.error: "Platform unsupported".}
|
|
||||||
when defined(MoreNimrod):
|
when defined(MoreNimrod):
|
||||||
{.hint: "MoreNimrod defined; some Chipmunk functions replaced in Nimrod".}
|
{.hint: "MoreNimrod defined; some Chipmunk functions replaced in Nimrod".}
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,9 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
"""
|
"""
|
||||||
when defined(Linux):
|
|
||||||
const Lib = "libenet.so.1(|.0.3)"
|
const Lib = "libenet.so.1(|.0.3)"
|
||||||
else:
|
|
||||||
{.error: "Your platform has not been accounted for."}
|
|
||||||
{.deadCodeElim: ON.}
|
{.deadCodeElim: ON.}
|
||||||
const
|
const
|
||||||
ENET_VERSION_MAJOR* = 1
|
ENET_VERSION_MAJOR* = 1
|
||||||
|
|
@ -267,7 +266,7 @@ const
|
||||||
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000
|
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000
|
||||||
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
|
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
|
||||||
|
|
||||||
when defined(Linux):
|
when defined(Linux) or true:
|
||||||
import posix
|
import posix
|
||||||
const
|
const
|
||||||
ENET_SOCKET_NULL*: cint = -1
|
ENET_SOCKET_NULL*: cint = -1
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@ when defined(linux):
|
||||||
LibS = "libcsfml-system.so.2.0"
|
LibS = "libcsfml-system.so.2.0"
|
||||||
LibW = "libcsfml-window.so.2.0"
|
LibW = "libcsfml-window.so.2.0"
|
||||||
else:
|
else:
|
||||||
{.error: "Platform unsupported".}
|
# We only compile for testing here, so it doesn't matter it's not supported
|
||||||
|
const
|
||||||
|
LibG = "libcsfml-graphics.so.2.0"
|
||||||
|
LibS = "libcsfml-system.so.2.0"
|
||||||
|
LibW = "libcsfml-window.so.2.0"
|
||||||
|
#{.error: "Platform unsupported".}
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
{.pragma: pf, pure, final.}
|
{.pragma: pf, pure, final.}
|
||||||
type
|
type
|
||||||
|
|
@ -153,8 +158,9 @@ type
|
||||||
KeyF15, #/< The F15 key
|
KeyF15, #/< The F15 key
|
||||||
KeyPause, #/< The Pause key
|
KeyPause, #/< The Pause key
|
||||||
KeyCount #/< Keep last -- the total number of keyboard keys
|
KeyCount #/< Keep last -- the total number of keyboard keys
|
||||||
when defined(linux): #or defined(bsd) ??
|
|
||||||
type TWindowHandle* = clong
|
type TWindowHandle* = clong
|
||||||
|
|
||||||
#elif defined(mac):
|
#elif defined(mac):
|
||||||
# type TWindowHandle* = pointer ##typedef void* sfWindowHandle; <- whatever the hell that is
|
# type TWindowHandle* = pointer ##typedef void* sfWindowHandle; <- whatever the hell that is
|
||||||
#elif defined(windows):
|
#elif defined(windows):
|
||||||
|
|
|
||||||
6
todo.txt
6
todo.txt
|
|
@ -1,9 +1,6 @@
|
||||||
version 0.9.4
|
version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- fix macros\tstringinterp.nim:
|
|
||||||
- problem: needs another level of indirection for 'seq'
|
|
||||||
- problem: deref is not correct
|
|
||||||
- fix GC issues
|
- fix GC issues
|
||||||
- test and fix showoff
|
- test and fix showoff
|
||||||
|
|
||||||
|
|
@ -26,7 +23,6 @@ version 0.9.x
|
||||||
|
|
||||||
- implement 'union' and 'bits' pragmas
|
- implement 'union' and 'bits' pragmas
|
||||||
- fix closures
|
- fix closures
|
||||||
- test and fix exception handling
|
|
||||||
- ensure (ref T)(a, b) works as a type conversion and type constructor
|
- ensure (ref T)(a, b) works as a type conversion and type constructor
|
||||||
- optimize 'genericReset'; 'newException' leads to code bloat
|
- optimize 'genericReset'; 'newException' leads to code bloat
|
||||||
- stack-less GC
|
- stack-less GC
|
||||||
|
|
@ -40,7 +36,7 @@ version 0.9.x
|
||||||
- built-in 'getImpl'
|
- built-in 'getImpl'
|
||||||
|
|
||||||
- change comment handling in the AST; that's lots of work as c2nim and pas2nim
|
- change comment handling in the AST; that's lots of work as c2nim and pas2nim
|
||||||
make use of the fast every node can have a comment!
|
make use of the fact every node can have a comment!
|
||||||
|
|
||||||
|
|
||||||
version 0.9.X
|
version 0.9.X
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue