diff options
Diffstat (limited to 'compiler/magicsys.nim')
-rw-r--r-- | compiler/magicsys.nim | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim new file mode 100644 index 000000000..1ec6b9a69 --- /dev/null +++ b/compiler/magicsys.nim @@ -0,0 +1,169 @@ +# +# +# The Nim Compiler +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Built-in types and compilerprocs are registered here. + +import + ast, astalgo, msgs, platform, idents, + modulegraphs, lineinfos + +export createMagic + +proc nilOrSysInt*(g: ModuleGraph): PType = g.sysTypes[tyInt] + +proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType = + result = newType(kind, g.idgen, g.systemModule) + result.size = size + result.align = size.int16 + +proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym = + result = systemModuleSym(g, getIdent(g.cache, name)) + if result == nil: + localError(g.config, info, "system module needs: " & name) + result = newSym(skError, getIdent(g.cache, name), g.idgen, g.systemModule, g.systemModule.info, {}) + result.typ = newType(tyError, g.idgen, g.systemModule) + +proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym = + result = nil + let id = getIdent(g.cache, name) + for r in systemModuleSyms(g, id): + if r.magic == m: + # prefer the tyInt variant: + if r.typ.returnType != nil and r.typ.returnType.kind == tyInt: return r + result = r + if result != nil: return result + localError(g.config, info, "system module needs: " & name) + result = newSym(skError, id, g.idgen, g.systemModule, g.systemModule.info, {}) + result.typ = newType(tyError, g.idgen, g.systemModule) + +proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType = + result = getSysSym(g, info, name).typ + +proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType = + template sysTypeFromName(s: string): untyped = sysTypeFromName(g, info, s) + result = g.sysTypes[kind] + if result == nil: + case kind + of tyVoid: result = sysTypeFromName("void") + of tyInt: result = sysTypeFromName("int") + of tyInt8: result = sysTypeFromName("int8") + of tyInt16: result = sysTypeFromName("int16") + of tyInt32: result = sysTypeFromName("int32") + of tyInt64: result = sysTypeFromName("int64") + of tyUInt: result = sysTypeFromName("uint") + of tyUInt8: result = sysTypeFromName("uint8") + of tyUInt16: result = sysTypeFromName("uint16") + of tyUInt32: result = sysTypeFromName("uint32") + of tyUInt64: result = sysTypeFromName("uint64") + of tyFloat: result = sysTypeFromName("float") + of tyFloat32: result = sysTypeFromName("float32") + of tyFloat64: result = sysTypeFromName("float64") + of tyFloat128: result = sysTypeFromName("float128") + of tyBool: result = sysTypeFromName("bool") + of tyChar: result = sysTypeFromName("char") + of tyString: result = sysTypeFromName("string") + of tyCstring: result = sysTypeFromName("cstring") + of tyPointer: result = sysTypeFromName("pointer") + of tyNil: result = newSysType(g, tyNil, g.config.target.ptrSize) + else: internalError(g.config, "request for typekind: " & $kind) + g.sysTypes[kind] = result + if result.kind != kind: + if kind == tyFloat64 and result.kind == tyFloat: discard # because of aliasing + else: + internalError(g.config, "wanted: " & $kind & " got: " & $result.kind) + if result == nil: internalError(g.config, "type not found: " & $kind) + +proc resetSysTypes*(g: ModuleGraph) = + g.systemModule = nil + g.compilerprocs = initStrTable() + g.exposed = initStrTable() + for i in low(g.sysTypes)..high(g.sysTypes): + g.sysTypes[i] = nil + +proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = + # for now we do not cache these: + result = newSysType(g, tyFloat, size=8) + result.n = literal + +proc skipIntLit*(t: PType; id: IdGenerator): PType {.inline.} = + if t.n != nil and t.kind in {tyInt, tyFloat}: + result = copyType(t, id, t.owner) + result.n = nil + else: + result = t + +proc addSonSkipIntLit*(father, son: PType; id: IdGenerator) = + let s = son.skipIntLit(id) + father.add(s) + propagateToOwner(father, s) + +proc makeVarType*(owner: PSym; baseType: PType; idgen: IdGenerator; kind = tyVar): PType = + if baseType.kind == kind: + result = baseType + else: + result = newType(kind, idgen, owner) + addSonSkipIntLit(result, baseType, idgen) + +proc getCompilerProc*(g: ModuleGraph; name: string): PSym = + let ident = getIdent(g.cache, name) + result = strTableGet(g.compilerprocs, ident) + if result == nil: + result = loadCompilerProc(g, name) + +proc registerCompilerProc*(g: ModuleGraph; s: PSym) = + strTableAdd(g.compilerprocs, s) + +proc registerNimScriptSymbol*(g: ModuleGraph; s: PSym) = + # Nimscript symbols must be al unique: + let conflict = strTableGet(g.exposed, s.name) + if conflict == nil: + strTableAdd(g.exposed, s) + else: + localError(g.config, s.info, + "symbol conflicts with other .exportNims symbol at: " & g.config$conflict.info) + +proc getNimScriptSymbol*(g: ModuleGraph; name: string): PSym = + strTableGet(g.exposed, getIdent(g.cache, name)) + +proc resetNimScriptSymbols*(g: ModuleGraph) = g.exposed = initStrTable() + +proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym = + case t.kind + of tyInt, tyInt8, tyInt16, tyInt32, tyInt64, + tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64: + result = getSysMagic(g, info, "==", mEqI) + of tyEnum: + result = getSysMagic(g, info, "==", mEqEnum) + of tyBool: + result = getSysMagic(g, info, "==", mEqB) + of tyRef, tyPtr, tyPointer: + result = getSysMagic(g, info, "==", mEqRef) + of tyString: + result = getSysMagic(g, info, "==", mEqStr) + of tyChar: + result = getSysMagic(g, info, "==", mEqCh) + of tySet: + result = getSysMagic(g, info, "==", mEqSet) + of tyProc: + result = getSysMagic(g, info, "==", mEqProc) + else: + result = nil + globalError(g.config, info, + "can't find magic equals operator for type kind " & $t.kind) + +proc makePtrType*(baseType: PType; idgen: IdGenerator): PType = + result = newType(tyPtr, idgen, baseType.owner) + addSonSkipIntLit(result, baseType, idgen) + +proc makeAddr*(n: PNode; idgen: IdGenerator): PNode = + if n.kind == nkHiddenAddr: + result = n + else: + result = newTree(nkHiddenAddr, n) + result.typ = makePtrType(n.typ, idgen) |