123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- template addAssignmentWithValue(builder: var Builder, lhs: Snippet, valueBody: typed) =
- builder.add(lhs)
- builder.add(" = ")
- valueBody
- builder.addLineEnd(";")
- template addFieldAssignmentWithValue(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
- builder.add(lhs)
- builder.add("." & name & " = ")
- valueBody
- builder.addLineEnd(";")
- template addAssignment(builder: var Builder, lhs, rhs: Snippet) =
- builder.addAssignmentWithValue(lhs):
- builder.add(rhs)
- template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: Snippet) =
- builder.addFieldAssignmentWithValue(lhs, name):
- builder.add(rhs)
- template addMutualFieldAssignment(builder: var Builder, lhs, rhs: Snippet, name: string) =
- builder.addFieldAssignmentWithValue(lhs, name):
- builder.add(rhs)
- builder.add("." & name)
- template addAssignment(builder: var Builder, lhs: Snippet, rhs: int | int64 | uint64 | Int128) =
- builder.addAssignmentWithValue(lhs):
- builder.addIntValue(rhs)
- template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: int | int64 | uint64 | Int128) =
- builder.addFieldAssignmentWithValue(lhs, name):
- builder.addIntValue(rhs)
- template addDerefFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: Snippet) =
- builder.add(lhs)
- builder.add("->" & name & " = ")
- builder.add(rhs)
- builder.addLineEnd(";")
- template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snippet, rhs: Snippet) =
- builder.add(lhs)
- builder.add("[" & index & "] = ")
- builder.add(rhs)
- builder.addLineEnd(";")
- template addStmt(builder: var Builder, stmtBody: typed) =
- ## makes an expression built by `stmtBody` into a statement
- stmtBody
- builder.addLineEnd(";")
- proc addCallStmt(builder: var Builder, callee: Snippet, args: varargs[Snippet]) =
- builder.addStmt():
- builder.addCall(callee, args)
- # XXX blocks need indent tracker in `Builder` object
- template addSingleIfStmt(builder: var Builder, cond: Snippet, body: typed) =
- builder.add("if (")
- builder.add(cond)
- builder.addLineEndIndent(") {")
- body
- builder.addLineEndDedent("}")
- template addSingleIfStmtWithCond(builder: var Builder, condBody: typed, body: typed) =
- builder.add("if (")
- condBody
- builder.addLineEndIndent(") {")
- body
- builder.addLineEndDedent("}")
- proc initIfStmt(builder: var Builder): IfBuilder =
- IfBuilder(state: WaitingIf)
- proc finishIfStmt(builder: var Builder, stmt: IfBuilder) =
- assert stmt.state != InBlock
- builder.addNewline()
- template addIfStmt(builder: var Builder, stmt: out IfBuilder, body: typed) =
- stmt = initIfStmt(builder)
- body
- finishIfStmt(builder, stmt)
- proc initElifBranch(builder: var Builder, stmt: var IfBuilder, cond: Snippet) =
- case stmt.state
- of WaitingIf:
- builder.add("if (")
- of WaitingElseIf:
- builder.add(" else if (")
- else: assert false, $stmt.state
- builder.add(cond)
- builder.addLineEndIndent(") {")
- stmt.state = InBlock
- proc initElseBranch(builder: var Builder, stmt: var IfBuilder) =
- assert stmt.state == WaitingElseIf, $stmt.state
- builder.addLineEndIndent(" else {")
- stmt.state = InBlock
- proc finishBranch(builder: var Builder, stmt: var IfBuilder) =
- builder.addDedent("}")
- stmt.state = WaitingElseIf
- template addElifBranch(builder: var Builder, stmt: var IfBuilder, cond: Snippet, body: typed) =
- initElifBranch(builder, stmt, cond)
- body
- finishBranch(builder, stmt)
- template addElseBranch(builder: var Builder, stmt: var IfBuilder, body: typed) =
- initElseBranch(builder, stmt)
- body
- finishBranch(builder, stmt)
- proc initForRange(builder: var Builder, i, start, bound: Snippet, inclusive: bool = false) =
- builder.add("for (")
- builder.add(i)
- builder.add(" = ")
- builder.add(start)
- builder.add("; ")
- builder.add(i)
- if inclusive:
- builder.add(" <= ")
- else:
- builder.add(" < ")
- builder.add(bound)
- builder.add("; ")
- builder.add(i)
- builder.addLineEndIndent("++) {")
- proc initForStep(builder: var Builder, i, start, bound, step: Snippet, inclusive: bool = false) =
- builder.add("for (")
- builder.add(i)
- builder.add(" = ")
- builder.add(start)
- builder.add("; ")
- builder.add(i)
- if inclusive:
- builder.add(" <= ")
- else:
- builder.add(" < ")
- builder.add(bound)
- builder.add("; ")
- builder.add(i)
- builder.add(" += ")
- builder.add(step)
- builder.addLineEndIndent(") {")
- proc finishFor(builder: var Builder) {.inline.} =
- builder.addLineEndDedent("}")
- template addForRangeExclusive(builder: var Builder, i, start, bound: Snippet, body: typed) =
- initForRange(builder, i, start, bound, false)
- body
- finishFor(builder)
- template addForRangeInclusive(builder: var Builder, i, start, bound: Snippet, body: typed) =
- initForRange(builder, i, start, bound, true)
- body
- finishFor(builder)
- template addSwitchStmt(builder: var Builder, val: Snippet, body: typed) =
- builder.add("switch (")
- builder.add(val)
- builder.addLineEnd(") {") # no indent
- body
- builder.addLineEnd("}")
- template addSingleSwitchCase(builder: var Builder, val: Snippet, body: typed) =
- builder.add("case ")
- builder.add(val)
- builder.addLineEndIndent(":")
- body
- builder.addLineEndDedent("")
- type
- SwitchCaseState = enum
- None, Of, Else, Finished
- SwitchCaseBuilder = object
- state: SwitchCaseState
- proc addCase(builder: var Builder, info: var SwitchCaseBuilder, val: Snippet) =
- if info.state != Of:
- assert info.state == None
- info.state = Of
- builder.add("case ")
- builder.add(val)
- builder.addLineEndIndent(":")
- proc addCaseRange(builder: var Builder, info: var SwitchCaseBuilder, first, last: Snippet) =
- if info.state != Of:
- assert info.state == None
- info.state = Of
- builder.add("case ")
- builder.add(first)
- builder.add(" ... ")
- builder.add(last)
- builder.addLineEndIndent(":")
- proc addCaseElse(builder: var Builder, info: var SwitchCaseBuilder) =
- assert info.state == None
- info.state = Else
- builder.addLineEndIndent("default:")
- template addSwitchCase(builder: var Builder, info: out SwitchCaseBuilder, caseBody, body: typed) =
- info = SwitchCaseBuilder(state: None)
- caseBody
- info.state = Finished
- body
- builder.addLineEndDedent("")
- template addSwitchElse(builder: var Builder, body: typed) =
- builder.addLineEndIndent("default:")
- body
- builder.addLineEndDedent("")
- proc addBreak(builder: var Builder) =
- builder.addLineEnd("break;")
- type ScopeBuilder = object
- inside: bool
- proc initScope(builder: var Builder): ScopeBuilder =
- builder.addLineEndIndent("{")
- result = ScopeBuilder(inside: true)
- proc finishScope(builder: var Builder, scope: var ScopeBuilder) =
- assert scope.inside, "scope not inited"
- builder.addLineEndDedent("}")
- scope.inside = false
- template addScope(builder: var Builder, body: typed) =
- builder.addLineEndIndent("{")
- body
- builder.addLineEndDedent("}")
- type WhileBuilder = object
- inside: bool
- proc initWhileStmt(builder: var Builder, cond: Snippet): WhileBuilder =
- builder.add("while (")
- builder.add(cond)
- builder.addLineEndIndent(") {")
- result = WhileBuilder(inside: true)
- proc finishWhileStmt(builder: var Builder, stmt: var WhileBuilder) =
- assert stmt.inside, "while stmt not inited"
- builder.addLineEndDedent("}")
- stmt.inside = false
- template addWhileStmt(builder: var Builder, cond: Snippet, body: typed) =
- builder.add("while (")
- builder.add(cond)
- builder.addLineEndIndent(") {")
- body
- builder.addLineEndDedent("}")
- proc addLabel(builder: var Builder, name: TLabel) =
- builder.add(name)
- builder.addLineEnd(": ;")
- proc addReturn(builder: var Builder) =
- builder.addLineEnd("return;")
- proc addReturn(builder: var Builder, value: Snippet) =
- builder.add("return ")
- builder.add(value)
- builder.addLineEnd(";")
- proc addGoto(builder: var Builder, label: TLabel) =
- builder.add("goto ")
- builder.add(label)
- builder.addLineEnd(";")
- proc addComputedGoto(builder: var Builder, value: Snippet) =
- builder.add("goto *")
- builder.add(value)
- builder.addLineEnd(";")
- proc addIncr(builder: var Builder, val: Snippet) =
- builder.add(val)
- builder.addLineEnd("++;")
- proc addDecr(builder: var Builder, val: Snippet) =
- builder.add(val)
- builder.addLineEnd("--;")
- proc addInPlaceOp(builder: var Builder, binOp: TypedBinaryOp, t: Snippet, a, b: Snippet) =
- builder.add(a)
- builder.add(' ')
- builder.add(typedBinaryOperators[binOp])
- builder.add("= ")
- builder.add(b)
- builder.addLineEnd(";")
- proc addInPlaceOp(builder: var Builder, binOp: UntypedBinaryOp, a, b: Snippet) =
- builder.add(a)
- builder.add(' ')
- builder.add(untypedBinaryOperators[binOp])
- builder.add("= ")
- builder.add(b)
- builder.addLineEnd(";")
- proc cInPlaceOp(binOp: TypedBinaryOp, t: Snippet, a, b: Snippet): Snippet =
- result = ""
- result.add(a)
- result.add(' ')
- result.add(typedBinaryOperators[binOp])
- result.add("= ")
- result.add(b)
- result.add(";\n")
- proc cInPlaceOp(binOp: UntypedBinaryOp, a, b: Snippet): Snippet =
- result = ""
- result.add(a)
- result.add(' ')
- result.add(untypedBinaryOperators[binOp])
- result.add("= ")
- result.add(b)
- result.add(";\n")
- template addCPragma(builder: var Builder, val: Snippet) =
- builder.addNewline()
- builder.add("#pragma ")
- builder.add(val)
- builder.addNewline()
- proc addDiscard(builder: var Builder, val: Snippet) =
- builder.add("(void)")
- builder.add(val)
- builder.addLineEnd(";")
|