fixes #686
This commit is contained in:
parent
f10a23e669
commit
2dcbc6493a
4 changed files with 166 additions and 20 deletions
|
|
@ -140,26 +140,27 @@ proc IsOpImpl(c: PContext, n: PNode): PNode
|
||||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode
|
semCheck: bool = true): PNode
|
||||||
|
|
||||||
proc symFromType(t: PType, info: TLineInfo): PSym =
|
when false:
|
||||||
if t.sym != nil: return t.sym
|
proc symFromType(t: PType, info: TLineInfo): PSym =
|
||||||
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
if t.sym != nil: return t.sym
|
||||||
result.flags.incl sfAnon
|
result = newSym(skType, getIdent"AnonType", t.owner, info)
|
||||||
result.typ = t
|
result.flags.incl sfAnon
|
||||||
|
result.typ = t
|
||||||
|
|
||||||
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
proc symNodeFromType(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||||
result = newSymNode(symFromType(t, info), info)
|
result = newSymNode(symFromType(t, info), info)
|
||||||
result.typ = makeTypeDesc(c, t)
|
result.typ = makeTypeDesc(c, t)
|
||||||
|
|
||||||
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
|
proc createEvalContext(c: PContext, mode: TEvalMode): PEvalContext =
|
||||||
result = newEvalContext(c.module, mode)
|
result = newEvalContext(c.module, mode)
|
||||||
result.getType = proc (n: PNode): PNode =
|
result.getType = proc (n: PNode): PNode =
|
||||||
var e = tryExpr(c, n)
|
result = tryExpr(c, n)
|
||||||
if e == nil:
|
if result == nil:
|
||||||
result = symNodeFromType(c, errorType(c), n.info)
|
result = newSymNode(errorSym(c, n))
|
||||||
elif e.typ == nil:
|
elif result.typ == nil:
|
||||||
result = newSymNode(getSysSym"void")
|
result = newSymNode(getSysSym"void")
|
||||||
else:
|
else:
|
||||||
result = symNodeFromType(c, e.typ, n.info)
|
result.typ = makeTypeDesc(c, result.typ)
|
||||||
|
|
||||||
result.handleIsOperator = proc (n: PNode): PNode =
|
result.handleIsOperator = proc (n: PNode): PNode =
|
||||||
result = IsOpImpl(c, n)
|
result = IsOpImpl(c, n)
|
||||||
|
|
@ -210,7 +211,8 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if n.kind == nkStmtList: result.kind = nkStmtListType
|
if n.kind == nkStmtList: result.kind = nkStmtListType
|
||||||
var typ = semTypeNode(c, result, nil)
|
var typ = semTypeNode(c, result, nil)
|
||||||
result = symNodeFromType(c, typ, n.info)
|
result.typ = makeTypeDesc(c, typ)
|
||||||
|
#result = symNodeFromType(c, typ, n.info)
|
||||||
else:
|
else:
|
||||||
result = semExpr(c, result)
|
result = semExpr(c, result)
|
||||||
result = fitNode(c, s.typ.sons[0], result)
|
result = fitNode(c, s.typ.sons[0], result)
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ proc isCastable(dst, src: PType): bool =
|
||||||
proc isSymChoice(n: PNode): bool {.inline.} =
|
proc isSymChoice(n: PNode): bool {.inline.} =
|
||||||
result = n.kind in nkSymChoices
|
result = n.kind in nkSymChoices
|
||||||
|
|
||||||
proc semConv(c: PContext, n: PNode, s: PSym): PNode =
|
proc semConv(c: PContext, n: PNode): PNode =
|
||||||
if sonsLen(n) != 2:
|
if sonsLen(n) != 2:
|
||||||
LocalError(n.info, errConvNeedsOneArg)
|
LocalError(n.info, errConvNeedsOneArg)
|
||||||
return n
|
return n
|
||||||
|
|
@ -738,8 +738,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
elif t != nil and t.kind == tyTypeDesc:
|
elif t != nil and t.kind == tyTypeDesc:
|
||||||
if n.len == 1: return semObjConstr(c, n, flags)
|
if n.len == 1: return semObjConstr(c, n, flags)
|
||||||
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
|
||||||
result = semConv(c, n, symFromType(destType, n.info))
|
return semConv(c, n)
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
result = overloadedCallOpr(c, n)
|
result = overloadedCallOpr(c, n)
|
||||||
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
# Now that nkSym does not imply an iteration over the proc/iterator space,
|
||||||
|
|
@ -1048,7 +1047,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# The result so far is a tyTypeDesc bound
|
# The result so far is a tyTypeDesc bound
|
||||||
# a tyGenericBody. The line below will substitute
|
# a tyGenericBody. The line below will substitute
|
||||||
# it with the instantiated type.
|
# it with the instantiated type.
|
||||||
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
result = n
|
||||||
|
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||||
|
#result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
n.sons[0] = makeDeref(n.sons[0])
|
n.sons[0] = makeDeref(n.sons[0])
|
||||||
|
|
@ -1883,7 +1884,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, n.sons[0], flags)
|
result = semExpr(c, n.sons[0], flags)
|
||||||
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
|
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy:
|
||||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||||
result = symNodeFromType(c, typ, n.info)
|
result.typ = makeTypeDesc(c, typ)
|
||||||
|
#result = symNodeFromType(c, typ, n.info)
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||||
# check if it is an expression macro:
|
# check if it is an expression macro:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -1906,7 +1908,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of skType:
|
of skType:
|
||||||
# XXX think about this more (``set`` procs)
|
# XXX think about this more (``set`` procs)
|
||||||
if n.len == 2:
|
if n.len == 2:
|
||||||
result = semConv(c, n, s)
|
result = semConv(c, n)
|
||||||
elif n.len == 1:
|
elif n.len == 1:
|
||||||
result = semObjConstr(c, n, flags)
|
result = semObjConstr(c, n, flags)
|
||||||
elif Contains(c.AmbiguousSymbols, s.id):
|
elif Contains(c.AmbiguousSymbols, s.id):
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,12 @@ proc foo(models: seq[TTable[string, float]]): seq[float] =
|
||||||
for model in models.items:
|
for model in models.items:
|
||||||
result.add model["foobar"]
|
result.add model["foobar"]
|
||||||
|
|
||||||
|
# bug #686
|
||||||
|
type TType[T; A] = array[A, T]
|
||||||
|
|
||||||
|
proc foo[T](p: TType[T, range[0..1]]) =
|
||||||
|
echo "foo"
|
||||||
|
proc foo[T](p: TType[T, range[0..2]]) =
|
||||||
|
echo "bar"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
134
tests/run/tdrdobbs_examples.nim
Normal file
134
tests/run/tdrdobbs_examples.nim
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
discard """
|
||||||
|
output: '''108
|
||||||
|
11 -1 1936
|
||||||
|
4.000000000000002-e001
|
||||||
|
true
|
||||||
|
truefalse'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc `++`(x: var int; y: int = 1; z: int = 0) =
|
||||||
|
x = x + y + z
|
||||||
|
|
||||||
|
var g = 70
|
||||||
|
++g
|
||||||
|
g ++ 7
|
||||||
|
g.`++`(10, 20)
|
||||||
|
echo g
|
||||||
|
|
||||||
|
|
||||||
|
#let lv = stdin.readline
|
||||||
|
#var vv = stdin.readline
|
||||||
|
#vv = "abc" # valid, reassignment allowed
|
||||||
|
#lv = "abc" # fails at compile time
|
||||||
|
|
||||||
|
#proc square(x: int): int = x*x
|
||||||
|
|
||||||
|
template square(x: int): int =
|
||||||
|
# ensure 'x' is only evaluated once:
|
||||||
|
let y = x
|
||||||
|
y * y
|
||||||
|
|
||||||
|
proc mostSignificantBit(n: int): int =
|
||||||
|
# naive algorithm:
|
||||||
|
var n = n
|
||||||
|
while n != 0:
|
||||||
|
n = n shr 1
|
||||||
|
result += 1
|
||||||
|
result -= 1
|
||||||
|
|
||||||
|
const msb3999 = mostSignificantBit(3999)
|
||||||
|
|
||||||
|
echo msb3999, " ", mostSignificantBit(0), " ", square(44)
|
||||||
|
|
||||||
|
proc filter[T](a: openarray[T], predicate: proc (x: T): bool): seq[T] =
|
||||||
|
result = @[] # @[] constructs the empty seq
|
||||||
|
for x in a:
|
||||||
|
if predicate(x): result.add(x)
|
||||||
|
|
||||||
|
proc map[T, S](a: openarray[T], fn: proc (x: T): S): seq[S] =
|
||||||
|
newSeq(result, a.len)
|
||||||
|
for i in 0 .. <a.len: result[i] = fn(a[i])
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
FormulaKind = enum
|
||||||
|
fkVar, ## element is a variable like 'X'
|
||||||
|
fkLit, ## element is a literal like 0.1
|
||||||
|
fkAdd, ## element is an addition operation
|
||||||
|
fkMul, ## element is a multiplication operation
|
||||||
|
fkExp ## element is an exponentiation operation
|
||||||
|
|
||||||
|
type
|
||||||
|
Formula = ref object
|
||||||
|
case kind: FormulaKind
|
||||||
|
of fkVar: name: string
|
||||||
|
of fkLit: value: float
|
||||||
|
of fkAdd, fkMul, fkExp: left, right: Formula
|
||||||
|
|
||||||
|
from math import pow
|
||||||
|
|
||||||
|
proc evaluate(n: Formula, varToVal: proc (name: string): float): float =
|
||||||
|
case n.kind
|
||||||
|
of fkVar: varToVal(n.name)
|
||||||
|
of fkLit: n.value
|
||||||
|
of fkAdd: evaluate(n.left, varToVal) + evaluate(n.right, varToVal)
|
||||||
|
of fkMul: evaluate(n.left, varToVal) * evaluate(n.right, varToVal)
|
||||||
|
of fkExp: pow(evaluate(n.left, varToVal), evaluate(n.right, varToVal))
|
||||||
|
|
||||||
|
echo evaluate(Formula(kind: fkLit, value: 0.4), nil)
|
||||||
|
|
||||||
|
proc isPolyTerm(n: Formula): bool =
|
||||||
|
n.kind == fkMul and n.left.kind == fkLit and (let e = n.right;
|
||||||
|
e.kind == fkExp and e.left.kind == fkVar and e.right.kind == fkLit)
|
||||||
|
|
||||||
|
proc isPolynomial(n: Formula): bool =
|
||||||
|
isPolyTerm(n) or
|
||||||
|
(n.kind == fkAdd and isPolynomial(n.left) and isPolynomial(n.right))
|
||||||
|
|
||||||
|
let myFormula = Formula(kind: fkMul,
|
||||||
|
left: Formula(kind: fkLit, value: 2.0),
|
||||||
|
right: Formula(kind: fkExp,
|
||||||
|
left: Formula(kind: fkVar, name: "x"),
|
||||||
|
right: Formula(kind: fkLit, value: 5.0)))
|
||||||
|
|
||||||
|
echo isPolyTerm(myFormula)
|
||||||
|
|
||||||
|
proc pat2kind(pattern: string): FormulaKind =
|
||||||
|
case pattern
|
||||||
|
of "^": fkExp
|
||||||
|
of "*": fkMul
|
||||||
|
of "+": fkAdd
|
||||||
|
of "x": fkVar
|
||||||
|
of "c": fkLit
|
||||||
|
else: fkVar # no error reporting for reasons of simplicity
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
proc matchAgainst(n, pattern: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
|
template `@`(current, field: expr): expr =
|
||||||
|
newDotExpr(current, newIdentNode(astToStr(field)))
|
||||||
|
|
||||||
|
template `==@`(n, pattern: expr): expr =
|
||||||
|
newCall("==", n@kind, newIdentNode($pat2kind($pattern.ident)))
|
||||||
|
|
||||||
|
case pattern.kind
|
||||||
|
of CallNodes:
|
||||||
|
result = newCall("and",
|
||||||
|
n ==@ pattern[0],
|
||||||
|
matchAgainst(n@left, pattern[1]))
|
||||||
|
if pattern.len == 3:
|
||||||
|
result = newCall("and", result.copy,
|
||||||
|
matchAgainst(n@right, pattern[2]))
|
||||||
|
of nnkIdent:
|
||||||
|
result = n ==@ pattern
|
||||||
|
of nnkPar:
|
||||||
|
result = matchAgainst(n, pattern[0])
|
||||||
|
else:
|
||||||
|
error "invalid pattern"
|
||||||
|
|
||||||
|
macro `=~` (n: Formula, pattern: expr): bool =
|
||||||
|
result = matchAgainst(n, pattern)
|
||||||
|
|
||||||
|
proc isPolyTerm2(n: Formula): bool = n =~ c * x^c
|
||||||
|
|
||||||
|
echo isPolyTerm2(myFormula), isPolyTerm2(Formula(kind: fkLit, value: 0.7))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue