diff options
Diffstat (limited to 'compiler/semmacrosanity.nim')
-rw-r--r-- | compiler/semmacrosanity.nim | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim index a6024a42f..727f36470 100644 --- a/compiler/semmacrosanity.nim +++ b/compiler/semmacrosanity.nim @@ -10,31 +10,40 @@ ## Implements type sanity checking for ASTs resulting from macros. Lots of ## room for improvement here. -import ast, astalgo, msgs, types +import ast, msgs, types, options proc ithField(n: PNode, field: var int): PSym = result = nil case n.kind of nkRecList: - for i in countup(0, sonsLen(n) - 1): - result = ithField(n.sons[i], field) + for i in 0..<n.len: + result = ithField(n[i], field) if result != nil: return of nkRecCase: - if n.sons[0].kind != nkSym: internalError(n.info, "ithField") - result = ithField(n.sons[0], field) + if n[0].kind != nkSym: return + result = ithField(n[0], field) if result != nil: return - for i in countup(1, sonsLen(n) - 1): - case n.sons[i].kind + for i in 1..<n.len: + case n[i].kind of nkOfBranch, nkElse: - result = ithField(lastSon(n.sons[i]), field) + result = ithField(lastSon(n[i]), field) if result != nil: return - else: internalError(n.info, "ithField(record case branch)") + else: discard of nkSym: if field == 0: result = n.sym else: dec(field) else: discard -proc annotateType*(n: PNode, t: PType) = +proc ithField(t: PType, field: var int): PSym = + var base = t.baseClass + while base != nil: + let b = skipTypes(base, skipPtrs) + result = ithField(b.n, field) + if result != nil: return result + base = b.baseClass + result = ithField(t.n, field) + +proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = let x = t.skipTypes(abstractInst+{tyRange}) # Note: x can be unequal to t and we need to be careful to use 't' # to not to skip tyGenericInst @@ -42,54 +51,76 @@ proc annotateType*(n: PNode, t: PType) = of nkObjConstr: let x = t.skipTypes(abstractPtrs) n.typ = t - for i in 1 .. <n.len: + n[0].typ = t + for i in 1..<n.len: var j = i-1 - let field = x.n.ithField(j) + let field = x.ithField(j) if field.isNil: - globalError n.info, "invalid field at index " & $i + globalError conf, n.info, "invalid field at index " & $i else: - internalAssert(n.sons[i].kind == nkExprColonExpr) - annotateType(n.sons[i].sons[1], field.typ) - of nkPar: + internalAssert(conf, n[i].kind == nkExprColonExpr) + annotateType(n[i][1], field.typ, conf) + of nkPar, nkTupleConstr: if x.kind == tyTuple: n.typ = t - for i in 0 .. <n.len: - if i >= x.len: globalError n.info, "invalid field at index " & $i - else: annotateType(n.sons[i], x.sons[i]) + for i in 0..<n.len: + if i >= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i + else: annotateType(n[i], x[i], conf) elif x.kind == tyProc and x.callConv == ccClosure: n.typ = t + elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples + if n.kind == nkTupleConstr: + let + bracketExpr = newNodeI(nkBracket, n.info) + left = int n[1].intVal + right = int n[2].intVal + bracketExpr.flags = n.flags + case n[0].kind # is this a string slice or a array slice + of nkStrKinds: + for i in left..right: + bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i]) + annotateType(bracketExpr[^1], x.elementType, conf) + of nkBracket: + for i in left..right: + bracketExpr.add n[0][i] + annotateType(bracketExpr[^1], x.elementType, conf) + else: + globalError(conf, n.info, "Incorrectly generated tuple constr") + n[] = bracketExpr[] + + n.typ = t else: - globalError(n.info, "() must have a tuple type") + globalError(conf, n.info, "() must have a tuple type") of nkBracket: if x.kind in {tyArray, tySequence, tyOpenArray}: n.typ = t - for m in n: annotateType(m, x.elemType) + for m in n: annotateType(m, x.elemType, conf) else: - globalError(n.info, "[] must have some form of array type") + globalError(conf, n.info, "[] must have some form of array type") of nkCurly: if x.kind in {tySet}: n.typ = t - for m in n: annotateType(m, x.elemType) + for m in n: annotateType(m, x.elemType, conf) else: - globalError(n.info, "{} must have the set type") + globalError(conf, n.info, "{} must have the set type") of nkFloatLit..nkFloat128Lit: if x.kind in {tyFloat..tyFloat128}: n.typ = t else: - globalError(n.info, "float literal must have some float type") + globalError(conf, n.info, "float literal must have some float type") of nkCharLit..nkUInt64Lit: if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}: n.typ = t else: - globalError(n.info, "integer literal must have some int type") + globalError(conf, n.info, "integer literal must have some int type") of nkStrLit..nkTripleStrLit: - if x.kind in {tyString, tyCString}: + if x.kind in {tyString, tyCstring}: n.typ = t else: - globalError(n.info, "string literal must be of some string type") + globalError(conf, n.info, "string literal must be of some string type") of nkNilLit: - if x.kind in NilableTypes: + if x.kind in NilableTypes+{tyString, tySequence}: n.typ = t else: - globalError(n.info, "nil literal must be of some pointer type") + globalError(conf, n.info, "nil literal must be of some pointer type") else: discard |