Moved the parseAST magics to evals.nim
Added string interpolation helper routines in parserutils
Added a proof-of-concept string interpolation user-land macros (currently, only as a test case):
the interpolated expression could either be transformed to
concat("literal string ", $(interpolated), " end") or
"literal string $1 end" % [$(interpolated)]
Added a very initial definition of Optional[T] generic type
A new overload of ParseIdent was added in hope to get around the fact that the
old one doesn't work correctly in macros, but the problem persists.
This commit is contained in:
parent
a28cf4e9cb
commit
dbcca9b3b9
6 changed files with 216 additions and 40 deletions
|
|
@ -16,7 +16,7 @@
|
|||
import
|
||||
strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets,
|
||||
msgs, os, condsyms, idents, renderer, types, passes, semfold, transf,
|
||||
ropes
|
||||
parser, ropes
|
||||
|
||||
type
|
||||
PStackFrame* = ref TStackFrame
|
||||
|
|
@ -752,6 +752,31 @@ proc evalRepr(c: PEvalContext, n: PNode): PNode =
|
|||
proc isEmpty(n: PNode): bool =
|
||||
result = (n != nil) and (n.kind == nkEmpty)
|
||||
|
||||
# The lexer marks multi-line strings as residing at the line where they are closed
|
||||
# This function returns the line where the string begins
|
||||
# Maybe the lexer should mark both the beginning and the end of expressions, then
|
||||
# this function could be removed
|
||||
proc stringStartingLine(s: PNode): int =
|
||||
var totalLines = 0
|
||||
for ln in splitLines(s.strVal): inc totalLines
|
||||
|
||||
result = s.info.line - totalLines
|
||||
|
||||
proc evalParseExpr(c: PEvalContext, n: Pnode): Pnode =
|
||||
var code = evalAux(c, n.sons[1], {})
|
||||
var ast = parseString(code.getStrValue, code.info.toFilename, code.stringStartingLine)
|
||||
|
||||
if sonsLen(ast) != 1:
|
||||
GlobalError(code.info, errExprExpected, "multiple statements")
|
||||
|
||||
result = ast.sons[0]
|
||||
result.typ = newType(tyExpr, c.module)
|
||||
|
||||
proc evalParseStmt(c: PEvalContext, n: Pnode): Pnode =
|
||||
var code = evalAux(c, n.sons[1], {})
|
||||
result = parseString(code.getStrValue, code.info.toFilename, code.stringStartingLine)
|
||||
result.typ = newType(tyStmt, c.module)
|
||||
|
||||
proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||
var m = getMagic(n)
|
||||
case m
|
||||
|
|
@ -776,6 +801,8 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
|||
of mAppendStrCh: result = evalAppendStrCh(c, n)
|
||||
of mAppendStrStr: result = evalAppendStrStr(c, n)
|
||||
of mAppendSeqElem: result = evalAppendSeqElem(c, n)
|
||||
of mParseExprToAst: result = evalParseExpr(c, n)
|
||||
of mParseStmtToAst: result = evalParseStmt(c, n)
|
||||
of mNLen:
|
||||
result = evalAux(c, n.sons[1], {efLValue})
|
||||
if isSpecial(result): return
|
||||
|
|
|
|||
|
|
@ -889,44 +889,16 @@ proc setMs(n: PNode, s: PSym): PNode =
|
|||
n.sons[0].info = n.info
|
||||
|
||||
proc expectStringArg(c: PContext, n: PNode, i: int): PNode =
|
||||
result = c.semConstExpr(c, n.sons[i+1])
|
||||
result = c.semAndEvalConstExpr(n.sons[i+1])
|
||||
|
||||
if result.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
|
||||
GlobalError(result.info, errStringLiteralExpected)
|
||||
|
||||
# The lexer marks multi-line strings as residing at the line where they are closed
|
||||
# This function returns the line where the string begins
|
||||
# Maybe the lexer should mark both the beginning and the end of expressions, then
|
||||
# this function could be removed
|
||||
proc stringStartingLine(s: PNode): int =
|
||||
var totalLines = 0
|
||||
for ln in splitLines(s.strVal): inc totalLines
|
||||
|
||||
result = s.info.line - totalLines
|
||||
|
||||
proc semParseExprToAst(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 2:
|
||||
var code = expectStringArg(c, n, 0)
|
||||
var ast = parseString(code.strVal, code.info.toFilename, code.stringStartingLine)
|
||||
|
||||
if sonsLen(ast) != 1:
|
||||
GlobalError(code.info, errExprExpected, "multiple statements")
|
||||
|
||||
result = newMetaNodeIT(ast.sons[0], code.info, newTypeS(tyExpr, c))
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
proc semParseStmtToAst(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 2:
|
||||
var code = expectStringArg(c, n, 0)
|
||||
var ast = parseString(code.strVal, code.info.toFilename, code.stringStartingLine)
|
||||
|
||||
result = newMetaNodeIT(ast, code.info, newTypeS(tyStmt, c))
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
GlobalError(result.info, errStringLiteralExpected)
|
||||
|
||||
proc semExpandMacroToAst(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 2 and isCallExpr(n.sons[1]):
|
||||
if sonsLen(n) == 2:
|
||||
if not isCallExpr(n.sons[1]):
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
|
||||
|
||||
var macroCall = n.sons[1]
|
||||
|
||||
var s = qualifiedLookup(c, macroCall.sons[0], {checkUndeclared})
|
||||
|
|
@ -943,7 +915,7 @@ proc semExpandMacroToAst(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
var macroRetType = newTypeS(s.typ.sons[0].kind, c)
|
||||
result = newMetaNodeIT(expanded, n.info, macroRetType)
|
||||
else:
|
||||
GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
proc semSlurp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if sonsLen(n) == 2:
|
||||
|
|
@ -981,8 +953,6 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
|||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
of mSlurp: result = semSlurp(c, n, flags)
|
||||
of mParseExprToAst: result = semParseExprToAst(c, n, flags)
|
||||
of mParseStmtToAst: result = semParseStmtToAst(c, n, flags)
|
||||
of mExpandMacroToAst: result = semExpandMacroToAst(c, n, flags)
|
||||
else: result = semDirectOp(c, n, flags)
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
|||
of mNewString, mNewStringOfCap,
|
||||
mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh,
|
||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||
mParseExprToAst, mParseStmtToAst,
|
||||
mNLen..mNError, mEqRef:
|
||||
nil
|
||||
else: InternalError(a.info, "evalOp(" & $m & ')')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue