parameter passing works the same for macros and templates; use callsite magic to access the invokation AST
This commit is contained in:
parent
6bcdb9c8f4
commit
b4844a189d
16 changed files with 270 additions and 180 deletions
|
|
@ -441,7 +441,7 @@ type
|
||||||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
||||||
mNBindSym,
|
mNBindSym, mNCallSite,
|
||||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
||||||
mInstantiationInfo, mGetTypeInfo
|
mInstantiationInfo, mGetTypeInfo
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ type
|
||||||
module*: PSym
|
module*: PSym
|
||||||
tos*: PStackFrame # top of stack
|
tos*: PStackFrame # top of stack
|
||||||
lastException*: PNode
|
lastException*: PNode
|
||||||
|
callsite: PNode # for 'callsite' magic
|
||||||
mode*: TEvalMode
|
mode*: TEvalMode
|
||||||
globals*: TIdNodeTable # state of global vars
|
globals*: TIdNodeTable # state of global vars
|
||||||
|
|
||||||
|
|
@ -74,7 +75,7 @@ proc popStackFrame*(c: PEvalContext) {.inline.} =
|
||||||
if c.tos != nil: c.tos = c.tos.next
|
if c.tos != nil: c.tos = c.tos.next
|
||||||
else: InternalError("popStackFrame")
|
else: InternalError("popStackFrame")
|
||||||
|
|
||||||
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode
|
proc evalMacroCall*(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode
|
||||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
|
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
|
||||||
|
|
||||||
proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
|
proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
|
||||||
|
|
@ -106,8 +107,11 @@ proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") =
|
||||||
proc isSpecial(n: PNode): bool {.inline.} =
|
proc isSpecial(n: PNode): bool {.inline.} =
|
||||||
result = n.kind == nkExceptBranch
|
result = n.kind == nkExceptBranch
|
||||||
|
|
||||||
proc myreset(n: PNode) {.inline.} =
|
proc myreset(n: PNode) =
|
||||||
when defined(system.reset): reset(n[])
|
when defined(system.reset):
|
||||||
|
var oldInfo = n.info
|
||||||
|
reset(n[])
|
||||||
|
n.info = oldInfo
|
||||||
|
|
||||||
proc evalIf(c: PEvalContext, n: PNode): PNode =
|
proc evalIf(c: PEvalContext, n: PNode): PNode =
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -245,6 +249,11 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
of tyObject:
|
of tyObject:
|
||||||
result = newNodeIT(nkPar, info, t)
|
result = newNodeIT(nkPar, info, t)
|
||||||
getNullValueAux(t.n, result)
|
getNullValueAux(t.n, result)
|
||||||
|
# initialize inherited fields:
|
||||||
|
var base = t.sons[0]
|
||||||
|
while base != nil:
|
||||||
|
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
||||||
|
base = base.sons[0]
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
result = newNodeIT(nkBracket, info, t)
|
result = newNodeIT(nkBracket, info, t)
|
||||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||||
|
|
@ -925,7 +934,7 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
||||||
# we want to replace it with nkIdent node featuring
|
# we want to replace it with nkIdent node featuring
|
||||||
# the original unmangled macro name.
|
# the original unmangled macro name.
|
||||||
macroCall.sons[0] = newIdentNode(expandedSym.name, expandedSym.info)
|
macroCall.sons[0] = newIdentNode(expandedSym.name, expandedSym.info)
|
||||||
result = evalMacroCall(c, macroCall, expandedSym)
|
result = evalMacroCall(c, macroCall, original, expandedSym)
|
||||||
else:
|
else:
|
||||||
InternalError(macroCall.info,
|
InternalError(macroCall.info,
|
||||||
"ExpandToAst: expanded symbol is no macro or template")
|
"ExpandToAst: expanded symbol is no macro or template")
|
||||||
|
|
@ -1166,9 +1175,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
of mIdentToStr:
|
of mIdentToStr:
|
||||||
result = evalAux(c, n.sons[1], {})
|
result = evalAux(c, n.sons[1], {})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
if result.kind != nkIdent: InternalError(n.info, "no ident node")
|
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||||
|
if a.kind == nkSym:
|
||||||
|
result.strVal = a.sym.name.s
|
||||||
|
else:
|
||||||
|
if a.kind != nkIdent: InternalError(n.info, "no ident node")
|
||||||
result.strVal = a.ident.s
|
result.strVal = a.ident.s
|
||||||
of mEqIdent:
|
of mEqIdent:
|
||||||
result = evalAux(c, n.sons[1], {})
|
result = evalAux(c, n.sons[1], {})
|
||||||
|
|
@ -1226,6 +1238,9 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||||
result.strVal = newString(0)
|
result.strVal = newString(0)
|
||||||
|
of mNCallSite:
|
||||||
|
if c.callsite != nil: result = c.callsite
|
||||||
|
else: stackTrace(c, n, errFieldXNotFound, "callsite")
|
||||||
else:
|
else:
|
||||||
result = evalAux(c, n.sons[1], {})
|
result = evalAux(c, n.sons[1], {})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
|
|
@ -1355,24 +1370,31 @@ proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
||||||
proc evalStaticExpr*(module: PSym, e: PNode): PNode =
|
proc evalStaticExpr*(module: PSym, e: PNode): PNode =
|
||||||
result = evalConstExprAux(module, e, emStatic)
|
result = evalConstExprAux(module, e, emStatic)
|
||||||
|
|
||||||
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
|
proc setupMacroParam(x: PNode): PNode =
|
||||||
|
result = x
|
||||||
|
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
||||||
|
|
||||||
|
proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||||
# XXX GlobalError() is ugly here, but I don't know a better solution for now
|
# XXX GlobalError() is ugly here, but I don't know a better solution for now
|
||||||
inc(evalTemplateCounter)
|
inc(evalTemplateCounter)
|
||||||
if evalTemplateCounter > 100:
|
if evalTemplateCounter > 100:
|
||||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||||
|
|
||||||
#inc genSymBaseId
|
c.callsite = nOrig
|
||||||
var s = newStackFrame()
|
var s = newStackFrame()
|
||||||
s.call = n
|
s.call = n
|
||||||
setlen(s.params, 2)
|
setlen(s.params, n.len)
|
||||||
|
# return value:
|
||||||
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
||||||
s.params[1] = n
|
# setup parameters:
|
||||||
|
for i in 1 .. < n.len: s.params[i] = setupMacroParam(n.sons[i])
|
||||||
pushStackFrame(c, s)
|
pushStackFrame(c, s)
|
||||||
discard eval(c, sym.getBody)
|
discard eval(c, sym.getBody)
|
||||||
result = s.params[0]
|
result = s.params[0]
|
||||||
popStackFrame(c)
|
popStackFrame(c)
|
||||||
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
|
c.callsite = nil
|
||||||
|
|
||||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||||
var c = newEvalContext(module, filename, emRepl)
|
var c = newEvalContext(module, filename, emRepl)
|
||||||
|
|
|
||||||
|
|
@ -774,7 +774,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||||
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
|
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
|
||||||
else:
|
else:
|
||||||
gsub(g, n.sons[1])
|
gsub(g, n.sons[1])
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[0])
|
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[1])
|
||||||
of nkCast:
|
of nkCast:
|
||||||
put(g, tkCast, "cast")
|
put(g, tkCast, "cast")
|
||||||
put(g, tkBracketLe, "[")
|
put(g, tkBracketLe, "[")
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||||
|
|
||||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
||||||
|
|
||||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode
|
semCheck: bool = true): PNode
|
||||||
|
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||||
|
|
@ -127,14 +127,14 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
|
|
||||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
semCheck: bool = true): PNode =
|
semCheck: bool = true): PNode =
|
||||||
markUsed(n, sym)
|
markUsed(n, sym)
|
||||||
if sym == c.p.owner:
|
if sym == c.p.owner:
|
||||||
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
|
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
|
||||||
if c.evalContext == nil:
|
if c.evalContext == nil:
|
||||||
c.evalContext = newEvalContext(c.module, "", emStatic)
|
c.evalContext = newEvalContext(c.module, "", emStatic)
|
||||||
result = evalMacroCall(c.evalContext, n, sym)
|
result = evalMacroCall(c.evalContext, n, nOrig, sym)
|
||||||
if semCheck: result = semAfterMacroCall(c, result, sym)
|
if semCheck: result = semAfterMacroCall(c, result, sym)
|
||||||
|
|
||||||
proc forceBool(c: PContext, n: PNode): PNode =
|
proc forceBool(c: PContext, n: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
else: result = newSymNode(s, n.info)
|
else: result = newSymNode(s, n.info)
|
||||||
else:
|
else:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
of skMacro: result = semMacroExpr(c, n, s)
|
of skMacro: result = semMacroExpr(c, n, n, s)
|
||||||
of skTemplate: result = semTemplateExpr(c, n, s)
|
of skTemplate: result = semTemplateExpr(c, n, s)
|
||||||
of skVar, skLet, skResult, skParam, skForVar:
|
of skVar, skLet, skResult, skParam, skForVar:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
|
|
@ -705,7 +705,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return errorNode(c, n)
|
return errorNode(c, n)
|
||||||
let callee = result.sons[0].sym
|
let callee = result.sons[0].sym
|
||||||
case callee.kind
|
case callee.kind
|
||||||
of skMacro: result = semMacroExpr(c, nOrig, callee)
|
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||||
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
|
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
|
||||||
else:
|
else:
|
||||||
fixAbstractType(c, result)
|
fixAbstractType(c, result)
|
||||||
|
|
@ -1399,6 +1399,7 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
|
||||||
Dec(c.p.nestedBlockCounter)
|
Dec(c.p.nestedBlockCounter)
|
||||||
|
|
||||||
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
|
# XXX why no overloading here?
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
var a: PNode
|
var a: PNode
|
||||||
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
||||||
|
|
@ -1407,7 +1408,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||||
if s != nil:
|
if s != nil:
|
||||||
case s.kind
|
case s.kind
|
||||||
of skMacro:
|
of skMacro:
|
||||||
result = semMacroExpr(c, n, s, semCheck)
|
result = semMacroExpr(c, n, n, s, semCheck)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
# transform
|
# transform
|
||||||
# nkMacroStmt(nkCall(a...), stmt, b...)
|
# nkMacroStmt(nkCall(a...), stmt, b...)
|
||||||
|
|
@ -1499,10 +1500,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
if s != nil:
|
if s != nil:
|
||||||
case s.kind
|
case s.kind
|
||||||
of skMacro:
|
of skMacro:
|
||||||
if false and sfImmediate notin s.flags: # XXX not yet enabled
|
if sfImmediate notin s.flags:
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
else:
|
else:
|
||||||
result = semMacroExpr(c, n, s)
|
result = semMacroExpr(c, n, n, s)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
if sfImmediate notin s.flags:
|
if sfImmediate notin s.flags:
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
result = semTemplateExpr(c, n, s, false)
|
result = semTemplateExpr(c, n, s, false)
|
||||||
of skMacro:
|
of skMacro:
|
||||||
result = semMacroExpr(c, n, s, false)
|
result = semMacroExpr(c, n, n, s, false)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
of skParam:
|
of skParam:
|
||||||
|
|
@ -97,7 +97,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
case s.kind
|
case s.kind
|
||||||
of skMacro:
|
of skMacro:
|
||||||
result = semMacroExpr(c, n, s, false)
|
result = semMacroExpr(c, n, n, s, false)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
result = semTemplateExpr(c, n, s, false)
|
result = semTemplateExpr(c, n, s, false)
|
||||||
# BUGFIX: we must not return here, we need to do first phase of
|
# BUGFIX: we must not return here, we need to do first phase of
|
||||||
|
|
|
||||||
|
|
@ -892,13 +892,10 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||||
checkSonsLen(n, bodyPos + 1)
|
checkSonsLen(n, bodyPos + 1)
|
||||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
|
||||||
LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
|
|
||||||
result = semProcAux(c, n, skMacro, macroPragmas)
|
result = semProcAux(c, n, skMacro, macroPragmas)
|
||||||
var s = result.sons[namePos].sym
|
var s = result.sons[namePos].sym
|
||||||
var t = s.typ
|
var t = s.typ
|
||||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
|
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
|
||||||
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
|
|
||||||
if n.sons[bodyPos].kind == nkEmpty:
|
if n.sons[bodyPos].kind == nkEmpty:
|
||||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -237,9 +237,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
return errorSym(c, n)
|
return errorSym(c, n)
|
||||||
if result.typ.kind != tyGenericParam:
|
if result.typ.kind != tyGenericParam:
|
||||||
# XXX get rid of this hack!
|
# XXX get rid of this hack!
|
||||||
|
var oldInfo = n.info
|
||||||
reset(n[])
|
reset(n[])
|
||||||
n.kind = nkSym
|
n.kind = nkSym
|
||||||
n.sym = result
|
n.sym = result
|
||||||
|
n.info = oldInfo
|
||||||
else:
|
else:
|
||||||
LocalError(n.info, errIdentifierExpected)
|
LocalError(n.info, errIdentifierExpected)
|
||||||
result = errorSym(c, n)
|
result = errorSym(c, n)
|
||||||
|
|
@ -549,7 +551,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
incl(result.flags, tfFinal)
|
incl(result.flags, tfFinal)
|
||||||
|
|
||||||
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||||
if kind == skMacro and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
if kind == skMacro:
|
||||||
|
# within a macro, every param has the type PNimrodNode!
|
||||||
|
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
||||||
let nn = getSysSym"PNimrodNode"
|
let nn = getSysSym"PNimrodNode"
|
||||||
var a = copySym(param)
|
var a = copySym(param)
|
||||||
a.typ = nn.typ
|
a.typ = nn.typ
|
||||||
|
|
@ -779,7 +783,7 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType =
|
||||||
markUsed(n, sym)
|
markUsed(n, sym)
|
||||||
case sym.kind
|
case sym.kind
|
||||||
of skMacro:
|
of skMacro:
|
||||||
result = semTypeNode(c, semMacroExpr(c, n, sym), nil)
|
result = semTypeNode(c, semMacroExpr(c, n, n, sym), nil)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
|
result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -3102,7 +3102,7 @@ a template. ``inject`` and ``gensym`` have no effect in ``dirty`` templates.
|
||||||
Macros
|
Macros
|
||||||
------
|
------
|
||||||
|
|
||||||
A `macro`:idx: is a special kind of low level template. They can be used
|
A `macro`:idx: is a special kind of low level template. Macros can be used
|
||||||
to implement `domain specific languages`:idx:. Like templates, macros come in
|
to implement `domain specific languages`:idx:. Like templates, macros come in
|
||||||
the 2 flavors *immediate* and *ordinary*.
|
the 2 flavors *immediate* and *ordinary*.
|
||||||
|
|
||||||
|
|
@ -3129,12 +3129,12 @@ variable number of arguments:
|
||||||
# ``macros`` module:
|
# ``macros`` module:
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro debug(n: expr): stmt =
|
macro debug(n: varargs[expr]): stmt =
|
||||||
# `n` is a Nimrod AST that contains the whole macro invocation
|
# `n` is a Nimrod AST that contains the whole macro invocation
|
||||||
# this macro returns a list of statements:
|
# this macro returns a list of statements:
|
||||||
result = newNimNode(nnkStmtList, n)
|
result = newNimNode(nnkStmtList, n)
|
||||||
# iterate over any argument that is passed to this macro:
|
# iterate over any argument that is passed to this macro:
|
||||||
for i in 1..n.len-1:
|
for i in 0..n.len-1:
|
||||||
# add a call to the statement list that writes the expression;
|
# add a call to the statement list that writes the expression;
|
||||||
# `toStrLit` converts an AST to its string representation:
|
# `toStrLit` converts an AST to its string representation:
|
||||||
add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
||||||
|
|
@ -3167,6 +3167,11 @@ The macro call expands to:
|
||||||
writeln(stdout, x)
|
writeln(stdout, x)
|
||||||
|
|
||||||
|
|
||||||
|
Arguments that are passed to a ``varargs`` parameter are wrapped in an array
|
||||||
|
constructor expression. This is why ``debug`` iterates over all of ``n``'s
|
||||||
|
children.
|
||||||
|
|
||||||
|
|
||||||
BindSym
|
BindSym
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
|
|
@ -3179,9 +3184,9 @@ builtin can be used for that:
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro debug(n: expr): stmt =
|
macro debug(n: varargs[expr]): stmt =
|
||||||
result = newNimNode(nnkStmtList, n)
|
result = newNimNode(nnkStmtList, n)
|
||||||
for i in 1..n.len-1:
|
for i in 0..n.len-1:
|
||||||
# we can bind symbols in scope via 'bindSym':
|
# we can bind symbols in scope via 'bindSym':
|
||||||
add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i])))
|
add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i])))
|
||||||
add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))
|
add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))
|
||||||
|
|
|
||||||
12
doc/tut2.txt
12
doc/tut2.txt
|
|
@ -67,7 +67,7 @@ Objects have access to their type at runtime. There is an
|
||||||
person: TPerson
|
person: TPerson
|
||||||
assert(student of TStudent) # is true
|
assert(student of TStudent) # is true
|
||||||
|
|
||||||
Object fields that should be visible from outside the defining module, have to
|
Object fields that should be visible from outside the defining module have to
|
||||||
be marked by ``*``. In contrast to tuples, different object types are
|
be marked by ``*``. In contrast to tuples, different object types are
|
||||||
never *equivalent*. New object types can only be defined within a type
|
never *equivalent*. New object types can only be defined within a type
|
||||||
section.
|
section.
|
||||||
|
|
@ -631,19 +631,19 @@ Expression Macros
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The following example implements a powerful ``debug`` command that accepts a
|
The following example implements a powerful ``debug`` command that accepts a
|
||||||
variable number of arguments (this cannot be done with templates):
|
variable number of arguments:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
# to work with Nimrod syntax trees, we need an API that is defined in the
|
# to work with Nimrod syntax trees, we need an API that is defined in the
|
||||||
# ``macros`` module:
|
# ``macros`` module:
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro debug(n: expr): stmt =
|
macro debug(n: varargs[expr]): stmt =
|
||||||
# `n` is a Nimrod AST that contains the whole macro expression
|
# `n` is a Nimrod AST that contains a list of expressions;
|
||||||
# this macro returns a list of statements:
|
# this macro returns a list of statements:
|
||||||
result = newNimNode(nnkStmtList, n)
|
result = newNimNode(nnkStmtList, n)
|
||||||
# iterate over any argument that is passed to this macro:
|
# iterate over any argument that is passed to this macro:
|
||||||
for i in 1..n.len-1:
|
for i in 0..n.len-1:
|
||||||
# add a call to the statement list that writes the expression;
|
# add a call to the statement list that writes the expression;
|
||||||
# `toStrLit` converts an AST to its string representation:
|
# `toStrLit` converts an AST to its string representation:
|
||||||
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
||||||
|
|
@ -702,5 +702,3 @@ regular expressions:
|
||||||
return tkOperator
|
return tkOperator
|
||||||
else:
|
else:
|
||||||
return tkUnknown
|
return tkUnknown
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,27 +96,25 @@ const
|
||||||
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
|
nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
|
||||||
nnkCallStrLit}
|
nnkCallStrLit}
|
||||||
|
|
||||||
# Nodes should be reference counted to make the `copy` operation very fast!
|
proc `[]`*(n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
|
||||||
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
|
|
||||||
# its father. How to do this without back references? Hm, BS, it works without
|
|
||||||
# them.
|
|
||||||
|
|
||||||
proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
|
|
||||||
## get `n`'s `i`'th child.
|
## get `n`'s `i`'th child.
|
||||||
|
|
||||||
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
proc `[]=`*(n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
|
||||||
## set `n`'s `i`'th child to `child`.
|
## set `n`'s `i`'th child to `child`.
|
||||||
|
|
||||||
proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
proc `!`*(s: string): TNimrodIdent {.magic: "StrToIdent".}
|
||||||
## constructs an identifier from the string `s`
|
## constructs an identifier from the string `s`
|
||||||
|
|
||||||
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
|
||||||
## converts a Nimrod identifier to a string
|
## converts a Nimrod identifier to a string
|
||||||
|
|
||||||
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
proc `$`*(s: PNimrodSymbol): string {.magic: "IdentToStr".}
|
||||||
|
## converts a Nimrod symbol to a string
|
||||||
|
|
||||||
|
proc `==`*(a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
|
||||||
## compares two Nimrod identifiers
|
## compares two Nimrod identifiers
|
||||||
|
|
||||||
proc `==`* (a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
|
proc `==`*(a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
|
||||||
## compares two Nimrod nodes
|
## compares two Nimrod nodes
|
||||||
|
|
||||||
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
proc len*(n: PNimrodNode): int {.magic: "NLen".}
|
||||||
|
|
@ -210,6 +208,9 @@ proc bindSym*(ident: string, rule: TBindSymRule = brClosed): PNimrodNode {.
|
||||||
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
|
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
|
||||||
## returned even if the symbol is not ambiguous.
|
## returned even if the symbol is not ambiguous.
|
||||||
|
|
||||||
|
proc callsite*(): PNimrodNode {.magic: "NCallSite".}
|
||||||
|
## returns the AST if the invokation expression that invoked this macro.
|
||||||
|
|
||||||
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||||
## converts the AST `n` to the concrete Nimrod code and wraps that
|
## converts the AST `n` to the concrete Nimrod code and wraps that
|
||||||
## in a string literal node
|
## in a string literal node
|
||||||
|
|
@ -246,15 +247,6 @@ template emit*(s: expr): stmt =
|
||||||
block:
|
block:
|
||||||
const evaluated = s
|
const evaluated = s
|
||||||
eval: result = evaluated.parseStmt
|
eval: result = evaluated.parseStmt
|
||||||
when false:
|
|
||||||
template once(x: expr): expr =
|
|
||||||
block:
|
|
||||||
const y = x
|
|
||||||
y
|
|
||||||
|
|
||||||
macro `payload`(x: stmt): stmt = result = once(s).parseStmt
|
|
||||||
`payload`()
|
|
||||||
|
|
||||||
|
|
||||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||||
## checks that `n` is of kind `k`. If this is not the case,
|
## checks that `n` is of kind `k`. If this is not the case,
|
||||||
|
|
@ -312,13 +304,8 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||||
## Convert the AST `n` to a human-readable tree-like string.
|
## Convert the AST `n` to a human-readable tree-like string.
|
||||||
##
|
##
|
||||||
## See also `repr` and `lispRepr`.
|
## See also `repr` and `lispRepr`.
|
||||||
|
|
||||||
proc traverse(res: var string, level: int, n: PNimrodNode) =
|
proc traverse(res: var string, level: int, n: PNimrodNode) =
|
||||||
for i in 0..level-1: res.add " "
|
for i in 0..level-1: res.add " "
|
||||||
|
|
||||||
if n == nil:
|
|
||||||
res.add "nil"
|
|
||||||
else:
|
|
||||||
res.add(($n.kind).substr(3))
|
res.add(($n.kind).substr(3))
|
||||||
|
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -328,7 +315,8 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||||
of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)
|
of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)
|
||||||
of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)
|
of nnkStrLit..nnkTripleStrLit: res.add(" " & $n.strVal)
|
||||||
of nnkIdent: res.add(" !\"" & $n.ident & '"')
|
of nnkIdent: res.add(" !\"" & $n.ident & '"')
|
||||||
of nnkSym, nnkNone: assert false
|
of nnkSym: res.add(" \"" & $n.symbol & '"')
|
||||||
|
of nnkNone: assert false
|
||||||
else:
|
else:
|
||||||
for j in 0..n.len-1:
|
for j in 0..n.len-1:
|
||||||
res.add "\n"
|
res.add "\n"
|
||||||
|
|
@ -342,8 +330,6 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||||
##
|
##
|
||||||
## See also `repr` and `treeRepr`.
|
## See also `repr` and `treeRepr`.
|
||||||
|
|
||||||
if n == nil: return "nil"
|
|
||||||
|
|
||||||
result = ($n.kind).substr(3)
|
result = ($n.kind).substr(3)
|
||||||
add(result, "(")
|
add(result, "(")
|
||||||
|
|
||||||
|
|
@ -363,7 +349,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||||
|
|
||||||
add(result, ")")
|
add(result, ")")
|
||||||
|
|
||||||
macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
macro dumpTree*(s: stmt): stmt = echo s.treeRepr
|
||||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||||
## tree using the `toTree` function. Printing is done *at compile time*.
|
## tree using the `toTree` function. Printing is done *at compile time*.
|
||||||
##
|
##
|
||||||
|
|
@ -371,7 +357,7 @@ macro dumpTree*(s: stmt): stmt = echo s[1].treeRepr
|
||||||
## tree and to discover what kind of nodes must be created to represent
|
## tree and to discover what kind of nodes must be created to represent
|
||||||
## a certain expression/statement.
|
## a certain expression/statement.
|
||||||
|
|
||||||
macro dumpLisp*(s: stmt): stmt = echo s[1].lispRepr
|
macro dumpLisp*(s: stmt): stmt = echo s.lispRepr
|
||||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||||
## tree using the `toLisp` function. Printing is done *at compile time*.
|
## tree using the `toLisp` function. Printing is done *at compile time*.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## var nim = "Nimrod"
|
## var nim = "Nimrod"
|
||||||
## echo h1(a(href="http://force7.de/nimrod", nim))
|
## echo h1(a(href="http://nimrod-code.org", nim))
|
||||||
##
|
##
|
||||||
## Writes the string::
|
## Writes the string::
|
||||||
##
|
##
|
||||||
## <h1><a href="http://force7.de/nimrod">Nimrod</a></h1>
|
## <h1><a href="http://nimrod-code.org">Nimrod</a></h1>
|
||||||
##
|
##
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -88,319 +88,394 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string,
|
||||||
result = NestList(!"&", result)
|
result = NestList(!"&", result)
|
||||||
|
|
||||||
|
|
||||||
macro a*(e: expr): expr =
|
macro a*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``a`` element.
|
## generates the HTML ``a`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " &
|
result = xmlCheckedTag(e, "a", "href charset type hreflang rel rev " &
|
||||||
"accesskey tabindex" & commonAttr)
|
"accesskey tabindex" & commonAttr)
|
||||||
|
|
||||||
macro acronym*(e: expr): expr =
|
macro acronym*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``acronym`` element.
|
## generates the HTML ``acronym`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "acronym", commonAttr)
|
result = xmlCheckedTag(e, "acronym", commonAttr)
|
||||||
|
|
||||||
macro address*(e: expr): expr =
|
macro address*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``address`` element.
|
## generates the HTML ``address`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "address", commonAttr)
|
result = xmlCheckedTag(e, "address", commonAttr)
|
||||||
|
|
||||||
macro area*(e: expr): expr =
|
macro area*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``area`` element.
|
## generates the HTML ``area`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "area", "shape coords href nohref" &
|
result = xmlCheckedTag(e, "area", "shape coords href nohref" &
|
||||||
" accesskey tabindex" & commonAttr, "alt", true)
|
" accesskey tabindex" & commonAttr, "alt", true)
|
||||||
|
|
||||||
macro b*(e: expr): expr =
|
macro b*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``b`` element.
|
## generates the HTML ``b`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "b", commonAttr)
|
result = xmlCheckedTag(e, "b", commonAttr)
|
||||||
|
|
||||||
macro base*(e: expr): expr =
|
macro base*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``base`` element.
|
## generates the HTML ``base`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "base", "", "href", true)
|
result = xmlCheckedTag(e, "base", "", "href", true)
|
||||||
|
|
||||||
macro big*(e: expr): expr =
|
macro big*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``big`` element.
|
## generates the HTML ``big`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "big", commonAttr)
|
result = xmlCheckedTag(e, "big", commonAttr)
|
||||||
|
|
||||||
macro blockquote*(e: expr): expr =
|
macro blockquote*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``blockquote`` element.
|
## generates the HTML ``blockquote`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr)
|
result = xmlCheckedTag(e, "blockquote", " cite" & commonAttr)
|
||||||
|
|
||||||
macro body*(e: expr): expr =
|
macro body*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``body`` element.
|
## generates the HTML ``body`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "body", commonAttr)
|
result = xmlCheckedTag(e, "body", commonAttr)
|
||||||
|
|
||||||
macro br*(e: expr): expr =
|
macro br*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``br`` element.
|
## generates the HTML ``br`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "br", "", "", true)
|
result = xmlCheckedTag(e, "br", "", "", true)
|
||||||
|
|
||||||
macro button*(e: expr): expr =
|
macro button*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``button`` element.
|
## generates the HTML ``button`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "button", "accesskey tabindex " &
|
result = xmlCheckedTag(e, "button", "accesskey tabindex " &
|
||||||
"disabled name type value" & commonAttr)
|
"disabled name type value" & commonAttr)
|
||||||
|
|
||||||
macro caption*(e: expr): expr =
|
macro caption*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``caption`` element.
|
## generates the HTML ``caption`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "caption", commonAttr)
|
result = xmlCheckedTag(e, "caption", commonAttr)
|
||||||
|
|
||||||
macro cite*(e: expr): expr =
|
macro cite*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``cite`` element.
|
## generates the HTML ``cite`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "cite", commonAttr)
|
result = xmlCheckedTag(e, "cite", commonAttr)
|
||||||
|
|
||||||
macro code*(e: expr): expr =
|
macro code*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``code`` element.
|
## generates the HTML ``code`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "code", commonAttr)
|
result = xmlCheckedTag(e, "code", commonAttr)
|
||||||
|
|
||||||
macro col*(e: expr): expr =
|
macro col*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``col`` element.
|
## generates the HTML ``col`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true)
|
result = xmlCheckedTag(e, "col", "span align valign" & commonAttr, "", true)
|
||||||
|
|
||||||
macro colgroup*(e: expr): expr =
|
macro colgroup*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``colgroup`` element.
|
## generates the HTML ``colgroup`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr)
|
result = xmlCheckedTag(e, "colgroup", "span align valign" & commonAttr)
|
||||||
|
|
||||||
macro dd*(e: expr): expr =
|
macro dd*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``dd`` element.
|
## generates the HTML ``dd`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "dd", commonAttr)
|
result = xmlCheckedTag(e, "dd", commonAttr)
|
||||||
|
|
||||||
macro del*(e: expr): expr =
|
macro del*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``del`` element.
|
## generates the HTML ``del`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
|
result = xmlCheckedTag(e, "del", "cite datetime" & commonAttr)
|
||||||
|
|
||||||
macro dfn*(e: expr): expr =
|
macro dfn*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``dfn`` element.
|
## generates the HTML ``dfn`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "dfn", commonAttr)
|
result = xmlCheckedTag(e, "dfn", commonAttr)
|
||||||
|
|
||||||
macro `div`*(e: expr): expr =
|
macro `div`*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``div`` element.
|
## generates the HTML ``div`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "div", commonAttr)
|
result = xmlCheckedTag(e, "div", commonAttr)
|
||||||
|
|
||||||
macro dl*(e: expr): expr =
|
macro dl*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``dl`` element.
|
## generates the HTML ``dl`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "dl", commonAttr)
|
result = xmlCheckedTag(e, "dl", commonAttr)
|
||||||
|
|
||||||
macro dt*(e: expr): expr =
|
macro dt*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``dt`` element.
|
## generates the HTML ``dt`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "dt", commonAttr)
|
result = xmlCheckedTag(e, "dt", commonAttr)
|
||||||
|
|
||||||
macro em*(e: expr): expr =
|
macro em*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``em`` element.
|
## generates the HTML ``em`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "em", commonAttr)
|
result = xmlCheckedTag(e, "em", commonAttr)
|
||||||
|
|
||||||
macro fieldset*(e: expr): expr =
|
macro fieldset*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``fieldset`` element.
|
## generates the HTML ``fieldset`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "fieldset", commonAttr)
|
result = xmlCheckedTag(e, "fieldset", commonAttr)
|
||||||
|
|
||||||
macro form*(e: expr): expr =
|
macro form*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``form`` element.
|
## generates the HTML ``form`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "form", "method encype accept accept-charset" &
|
result = xmlCheckedTag(e, "form", "method encype accept accept-charset" &
|
||||||
commonAttr, "action")
|
commonAttr, "action")
|
||||||
|
|
||||||
macro h1*(e: expr): expr =
|
macro h1*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h1`` element.
|
## generates the HTML ``h1`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h1", commonAttr)
|
result = xmlCheckedTag(e, "h1", commonAttr)
|
||||||
|
|
||||||
macro h2*(e: expr): expr =
|
macro h2*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h2`` element.
|
## generates the HTML ``h2`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h2", commonAttr)
|
result = xmlCheckedTag(e, "h2", commonAttr)
|
||||||
|
|
||||||
macro h3*(e: expr): expr =
|
macro h3*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h3`` element.
|
## generates the HTML ``h3`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h3", commonAttr)
|
result = xmlCheckedTag(e, "h3", commonAttr)
|
||||||
|
|
||||||
macro h4*(e: expr): expr =
|
macro h4*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h4`` element.
|
## generates the HTML ``h4`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h4", commonAttr)
|
result = xmlCheckedTag(e, "h4", commonAttr)
|
||||||
|
|
||||||
macro h5*(e: expr): expr =
|
macro h5*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h5`` element.
|
## generates the HTML ``h5`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h5", commonAttr)
|
result = xmlCheckedTag(e, "h5", commonAttr)
|
||||||
|
|
||||||
macro h6*(e: expr): expr =
|
macro h6*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``h6`` element.
|
## generates the HTML ``h6`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "h6", commonAttr)
|
result = xmlCheckedTag(e, "h6", commonAttr)
|
||||||
|
|
||||||
macro head*(e: expr): expr =
|
macro head*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``head`` element.
|
## generates the HTML ``head`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "head", "profile")
|
result = xmlCheckedTag(e, "head", "profile")
|
||||||
|
|
||||||
macro html*(e: expr): expr =
|
macro html*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``html`` element.
|
## generates the HTML ``html`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "html", "xmlns", "")
|
result = xmlCheckedTag(e, "html", "xmlns", "")
|
||||||
|
|
||||||
macro hr*(e: expr): expr =
|
macro hr*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``hr`` element.
|
## generates the HTML ``hr`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "hr", commonAttr, "", true)
|
result = xmlCheckedTag(e, "hr", commonAttr, "", true)
|
||||||
|
|
||||||
macro i*(e: expr): expr =
|
macro i*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``i`` element.
|
## generates the HTML ``i`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "i", commonAttr)
|
result = xmlCheckedTag(e, "i", commonAttr)
|
||||||
|
|
||||||
macro img*(e: expr): expr =
|
macro img*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``img`` element.
|
## generates the HTML ``img`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true)
|
result = xmlCheckedTag(e, "img", "longdesc height width", "src alt", true)
|
||||||
|
|
||||||
macro input*(e: expr): expr =
|
macro input*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``input`` element.
|
## generates the HTML ``input`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "input", "name type value checked maxlength src" &
|
result = xmlCheckedTag(e, "input", "name type value checked maxlength src" &
|
||||||
" alt accept disabled readonly accesskey tabindex" & commonAttr, "", true)
|
" alt accept disabled readonly accesskey tabindex" & commonAttr, "", true)
|
||||||
|
|
||||||
macro ins*(e: expr): expr =
|
macro ins*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``ins`` element.
|
## generates the HTML ``ins`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr)
|
result = xmlCheckedTag(e, "ins", "cite datetime" & commonAttr)
|
||||||
|
|
||||||
macro kbd*(e: expr): expr =
|
macro kbd*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``kbd`` element.
|
## generates the HTML ``kbd`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "kbd", commonAttr)
|
result = xmlCheckedTag(e, "kbd", commonAttr)
|
||||||
|
|
||||||
macro label*(e: expr): expr =
|
macro label*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``label`` element.
|
## generates the HTML ``label`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr)
|
result = xmlCheckedTag(e, "label", "for accesskey" & commonAttr)
|
||||||
|
|
||||||
macro legend*(e: expr): expr =
|
macro legend*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``legend`` element.
|
## generates the HTML ``legend`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr)
|
result = xmlCheckedTag(e, "legend", "accesskey" & commonAttr)
|
||||||
|
|
||||||
macro li*(e: expr): expr =
|
macro li*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``li`` element.
|
## generates the HTML ``li`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "li", commonAttr)
|
result = xmlCheckedTag(e, "li", commonAttr)
|
||||||
|
|
||||||
macro link*(e: expr): expr =
|
macro link*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``link`` element.
|
## generates the HTML ``link`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" &
|
result = xmlCheckedTag(e, "link", "href charset hreflang type rel rev media" &
|
||||||
commonAttr, "", true)
|
commonAttr, "", true)
|
||||||
|
|
||||||
macro map*(e: expr): expr =
|
macro map*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``map`` element.
|
## generates the HTML ``map`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false)
|
result = xmlCheckedTag(e, "map", "class title" & eventAttr, "id", false)
|
||||||
|
|
||||||
macro meta*(e: expr): expr =
|
macro meta*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``meta`` element.
|
## generates the HTML ``meta`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true)
|
result = xmlCheckedTag(e, "meta", "name http-equiv scheme", "content", true)
|
||||||
|
|
||||||
macro noscript*(e: expr): expr =
|
macro noscript*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``noscript`` element.
|
## generates the HTML ``noscript`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "noscript", commonAttr)
|
result = xmlCheckedTag(e, "noscript", commonAttr)
|
||||||
|
|
||||||
macro `object`*(e: expr): expr =
|
macro `object`*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``object`` element.
|
## generates the HTML ``object`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "object", "classid data codebase declare type " &
|
result = xmlCheckedTag(e, "object", "classid data codebase declare type " &
|
||||||
"codetype archive standby width height name tabindex" & commonAttr)
|
"codetype archive standby width height name tabindex" & commonAttr)
|
||||||
|
|
||||||
macro ol*(e: expr): expr =
|
macro ol*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``ol`` element.
|
## generates the HTML ``ol`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "ol", commonAttr)
|
result = xmlCheckedTag(e, "ol", commonAttr)
|
||||||
|
|
||||||
macro optgroup*(e: expr): expr =
|
macro optgroup*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``optgroup`` element.
|
## generates the HTML ``optgroup`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false)
|
result = xmlCheckedTag(e, "optgroup", "disabled" & commonAttr, "label", false)
|
||||||
|
|
||||||
macro option*(e: expr): expr =
|
macro option*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``option`` element.
|
## generates the HTML ``option`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "option", "selected value" & commonAttr)
|
result = xmlCheckedTag(e, "option", "selected value" & commonAttr)
|
||||||
|
|
||||||
macro p*(e: expr): expr =
|
macro p*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``p`` element.
|
## generates the HTML ``p`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "p", commonAttr)
|
result = xmlCheckedTag(e, "p", commonAttr)
|
||||||
|
|
||||||
macro param*(e: expr): expr =
|
macro param*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``param`` element.
|
## generates the HTML ``param`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true)
|
result = xmlCheckedTag(e, "param", "value id type valuetype", "name", true)
|
||||||
|
|
||||||
macro pre*(e: expr): expr =
|
macro pre*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``pre`` element.
|
## generates the HTML ``pre`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "pre", commonAttr)
|
result = xmlCheckedTag(e, "pre", commonAttr)
|
||||||
|
|
||||||
macro q*(e: expr): expr =
|
macro q*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``q`` element.
|
## generates the HTML ``q`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "q", "cite" & commonAttr)
|
result = xmlCheckedTag(e, "q", "cite" & commonAttr)
|
||||||
|
|
||||||
macro samp*(e: expr): expr =
|
macro samp*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``samp`` element.
|
## generates the HTML ``samp`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "samp", commonAttr)
|
result = xmlCheckedTag(e, "samp", commonAttr)
|
||||||
|
|
||||||
macro script*(e: expr): expr =
|
macro script*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``script`` element.
|
## generates the HTML ``script`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "script", "src charset defer", "type", false)
|
result = xmlCheckedTag(e, "script", "src charset defer", "type", false)
|
||||||
|
|
||||||
macro select*(e: expr): expr =
|
macro select*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``select`` element.
|
## generates the HTML ``select`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" &
|
result = xmlCheckedTag(e, "select", "name size multiple disabled tabindex" &
|
||||||
commonAttr)
|
commonAttr)
|
||||||
|
|
||||||
macro small*(e: expr): expr =
|
macro small*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``small`` element.
|
## generates the HTML ``small`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "small", commonAttr)
|
result = xmlCheckedTag(e, "small", commonAttr)
|
||||||
|
|
||||||
macro span*(e: expr): expr =
|
macro span*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``span`` element.
|
## generates the HTML ``span`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "span", commonAttr)
|
result = xmlCheckedTag(e, "span", commonAttr)
|
||||||
|
|
||||||
macro strong*(e: expr): expr =
|
macro strong*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``strong`` element.
|
## generates the HTML ``strong`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "strong", commonAttr)
|
result = xmlCheckedTag(e, "strong", commonAttr)
|
||||||
|
|
||||||
macro style*(e: expr): expr =
|
macro style*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``style`` element.
|
## generates the HTML ``style`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "style", "media title", "type")
|
result = xmlCheckedTag(e, "style", "media title", "type")
|
||||||
|
|
||||||
macro sub*(e: expr): expr =
|
macro sub*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``sub`` element.
|
## generates the HTML ``sub`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "sub", commonAttr)
|
result = xmlCheckedTag(e, "sub", commonAttr)
|
||||||
|
|
||||||
macro sup*(e: expr): expr =
|
macro sup*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``sup`` element.
|
## generates the HTML ``sup`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "sup", commonAttr)
|
result = xmlCheckedTag(e, "sup", commonAttr)
|
||||||
|
|
||||||
macro table*(e: expr): expr =
|
macro table*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``table`` element.
|
## generates the HTML ``table`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" &
|
result = xmlCheckedTag(e, "table", "summary border cellpadding cellspacing" &
|
||||||
" frame rules width" & commonAttr)
|
" frame rules width" & commonAttr)
|
||||||
|
|
||||||
macro tbody*(e: expr): expr =
|
macro tbody*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``tbody`` element.
|
## generates the HTML ``tbody`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr)
|
result = xmlCheckedTag(e, "tbody", "align valign" & commonAttr)
|
||||||
|
|
||||||
macro td*(e: expr): expr =
|
macro td*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``td`` element.
|
## generates the HTML ``td`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" &
|
result = xmlCheckedTag(e, "td", "colspan rowspan abbr axis headers scope" &
|
||||||
" align valign" & commonAttr)
|
" align valign" & commonAttr)
|
||||||
|
|
||||||
macro textarea*(e: expr): expr =
|
macro textarea*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``textarea`` element.
|
## generates the HTML ``textarea`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" &
|
result = xmlCheckedTag(e, "textarea", " name disabled readonly accesskey" &
|
||||||
" tabindex" & commonAttr, "rows cols", false)
|
" tabindex" & commonAttr, "rows cols", false)
|
||||||
|
|
||||||
macro tfoot*(e: expr): expr =
|
macro tfoot*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``tfoot`` element.
|
## generates the HTML ``tfoot`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr)
|
result = xmlCheckedTag(e, "tfoot", "align valign" & commonAttr)
|
||||||
|
|
||||||
macro th*(e: expr): expr =
|
macro th*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``th`` element.
|
## generates the HTML ``th`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" &
|
result = xmlCheckedTag(e, "th", "colspan rowspan abbr axis headers scope" &
|
||||||
" align valign" & commonAttr)
|
" align valign" & commonAttr)
|
||||||
|
|
||||||
macro thead*(e: expr): expr =
|
macro thead*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``thead`` element.
|
## generates the HTML ``thead`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "thead", "align valign" & commonAttr)
|
result = xmlCheckedTag(e, "thead", "align valign" & commonAttr)
|
||||||
|
|
||||||
macro title*(e: expr): expr =
|
macro title*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``title`` element.
|
## generates the HTML ``title`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "title")
|
result = xmlCheckedTag(e, "title")
|
||||||
|
|
||||||
macro tr*(e: expr): expr =
|
macro tr*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``tr`` element.
|
## generates the HTML ``tr`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "tr", "align valign" & commonAttr)
|
result = xmlCheckedTag(e, "tr", "align valign" & commonAttr)
|
||||||
|
|
||||||
macro tt*(e: expr): expr =
|
macro tt*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``tt`` element.
|
## generates the HTML ``tt`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "tt", commonAttr)
|
result = xmlCheckedTag(e, "tt", commonAttr)
|
||||||
|
|
||||||
macro ul*(e: expr): expr =
|
macro ul*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``ul`` element.
|
## generates the HTML ``ul`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "ul", commonAttr)
|
result = xmlCheckedTag(e, "ul", commonAttr)
|
||||||
|
|
||||||
macro `var`*(e: expr): expr =
|
macro `var`*(e: expr): expr {.immediate.} =
|
||||||
## generates the HTML ``var`` element.
|
## generates the HTML ``var`` element.
|
||||||
|
let e = callsite()
|
||||||
result = xmlCheckedTag(e, "var", commonAttr)
|
result = xmlCheckedTag(e, "var", commonAttr)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var nim = "Nimrod"
|
var nim = "Nimrod"
|
||||||
echo h1(a(href="http://force7.de/nimrod", nim))
|
echo h1(a(href="http://nimrod-code.org", nim))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -325,8 +325,9 @@ proc styledEchoProcessArg(style: set[TStyle]) = setStyle style
|
||||||
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
||||||
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
||||||
|
|
||||||
macro styledEcho*(m: stmt): stmt =
|
macro styledEcho*(m: varargs[expr]): stmt =
|
||||||
## to be documented.
|
## to be documented.
|
||||||
|
let m = callsite()
|
||||||
result = newNimNode(nnkStmtList)
|
result = newNimNode(nnkStmtList)
|
||||||
|
|
||||||
for i in countup(1, m.len - 1):
|
for i in countup(1, m.len - 1):
|
||||||
|
|
|
||||||
|
|
@ -262,12 +262,13 @@ macro `<>`*(x: expr): expr =
|
||||||
## Constructor macro for XML. Example usage:
|
## Constructor macro for XML. Example usage:
|
||||||
##
|
##
|
||||||
## .. code-block:: nimrod
|
## .. code-block:: nimrod
|
||||||
## <>a(href="http://force7.de/nimrod", "Nimrod rules.")
|
## <>a(href="http://nimrod-code.org", "Nimrod rules.")
|
||||||
##
|
##
|
||||||
## Produces an XML tree for::
|
## Produces an XML tree for::
|
||||||
##
|
##
|
||||||
## <a href="http://force7.de/nimrod">Nimrod rules.</a>
|
## <a href="http://nimrod-code.org">Nimrod rules.</a>
|
||||||
##
|
##
|
||||||
|
let x = callsite()
|
||||||
result = xmlConstructor(x)
|
result = xmlConstructor(x)
|
||||||
|
|
||||||
proc child*(n: PXmlNode, name: string): PXmlNode =
|
proc child*(n: PXmlNode, name: string): PXmlNode =
|
||||||
|
|
|
||||||
32
todo.txt
32
todo.txt
|
|
@ -1,7 +1,9 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- introduce 'callsite' magic and make macros and templates the same
|
- make 'm: stmt' use overloading resolution
|
||||||
|
|
||||||
|
- implement the high level optimizer
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
|
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
|
|
@ -32,6 +34,17 @@ Bugs
|
||||||
version 0.9.XX
|
version 0.9.XX
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
- make:
|
||||||
|
p(a, b):
|
||||||
|
echo a
|
||||||
|
echo b
|
||||||
|
|
||||||
|
the same as:
|
||||||
|
|
||||||
|
p(a, b, proc() =
|
||||||
|
echo a
|
||||||
|
echo b)
|
||||||
|
|
||||||
- JS gen:
|
- JS gen:
|
||||||
- fix exception handling
|
- fix exception handling
|
||||||
|
|
||||||
|
|
@ -52,7 +65,6 @@ version 0.9.XX
|
||||||
- document nimdoc properly finally
|
- document nimdoc properly finally
|
||||||
- make 'clamp' a magic for the range stuff
|
- make 'clamp' a magic for the range stuff
|
||||||
- implement a warning message for shadowed 'result' variable
|
- implement a warning message for shadowed 'result' variable
|
||||||
- implement the high level optimizer
|
|
||||||
- we need to support iteration of 2 different data structures in parallel
|
- we need to support iteration of 2 different data structures in parallel
|
||||||
- implement proper coroutines
|
- implement proper coroutines
|
||||||
- proc specialization in the code gen for write barrier specialization
|
- proc specialization in the code gen for write barrier specialization
|
||||||
|
|
@ -71,17 +83,6 @@ version 0.9.XX
|
||||||
* For parameter ``tyExpr`` any argument matches.
|
* For parameter ``tyExpr`` any argument matches.
|
||||||
* Argument ``tyProxy`` matches any parameter.
|
* Argument ``tyProxy`` matches any parameter.
|
||||||
|
|
||||||
- nice idea:
|
|
||||||
|
|
||||||
p(a, b):
|
|
||||||
echo a
|
|
||||||
echo b
|
|
||||||
|
|
||||||
is the same as:
|
|
||||||
|
|
||||||
p(a, b, proc() =
|
|
||||||
echo a
|
|
||||||
echo b)
|
|
||||||
|
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
@ -114,10 +115,7 @@ Low priority
|
||||||
escape analysis for string/seq seems to be easy to do too;
|
escape analysis for string/seq seems to be easy to do too;
|
||||||
even further write barrier specialization
|
even further write barrier specialization
|
||||||
- GC: marker procs Boehm GC
|
- GC: marker procs Boehm GC
|
||||||
- implement marker procs for assignment and message passing
|
- implement marker procs for message passing
|
||||||
- warning for implicit openArray -> varargs conversion
|
|
||||||
- implement explicit varargs; **but** ``len(varargs)`` problem remains!
|
|
||||||
--> solve by implicit conversion from varargs to openarray
|
|
||||||
- optimize method dispatchers
|
- optimize method dispatchers
|
||||||
- activate more thread tests
|
- activate more thread tests
|
||||||
- implement ``--script:sh|bat`` command line option; think about script
|
- implement ``--script:sh|bat`` command line option; think about script
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ Changes affecting backwards compatibility
|
||||||
- Objects that have no ancestor are now implicitely ``final``. Use
|
- Objects that have no ancestor are now implicitely ``final``. Use
|
||||||
the ``inheritable`` pragma to introduce new object roots apart
|
the ``inheritable`` pragma to introduce new object roots apart
|
||||||
from ``TObject``.
|
from ``TObject``.
|
||||||
|
- Macros now receive parameters like templates do; use the ``callsite`` builtin
|
||||||
|
to gain access to the invokating AST.
|
||||||
|
|
||||||
|
|
||||||
Compiler Additions
|
Compiler Additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue