parent
d1d7d9e3fe
commit
201a08e9a5
10 changed files with 249 additions and 55 deletions
174
tests/vm/tasmparser.nim
Normal file
174
tests/vm/tasmparser.nim
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
|
||||
# bug #1513
|
||||
|
||||
import os, parseutils, strutils, ropes, macros
|
||||
|
||||
var
|
||||
code {.compileTime.} = ""
|
||||
start {.compileTime.} = 0
|
||||
line {.compileTime.} = 1
|
||||
cpp {.compileTime.} = ""
|
||||
token {.compileTime.} = ""
|
||||
|
||||
proc log (msg: string) {.compileTime.} =
|
||||
echo msg
|
||||
|
||||
proc asmx64 () {.compileTime} =
|
||||
|
||||
#log "code = $1" % code
|
||||
|
||||
const asmx64pre = "{.emit: \"\"\"{x64asm& x= *x64asm_ptr(`asm0`); try {"
|
||||
const asmx64post = "} catch (Xbyak::Error e) { printf (\"asmx64 error: %s\\n\", e.what ()); }}\"\"\".} "
|
||||
|
||||
const xp = "x."
|
||||
|
||||
const symbolStart = { '_', 'a'..'z', 'A' .. 'Z' }
|
||||
const symbol = { '0'..'9' } + symbolStart
|
||||
const eolComment = { ';' }
|
||||
const endOfLine = { '\l', '\r' }
|
||||
const leadingWhiteSpace = { ' ' }
|
||||
|
||||
const end_or_comment = endOfLine + eolComment + { '\0' }
|
||||
|
||||
const passthrough_start = { '{', '`' }
|
||||
const passthrough_end = { '}', '`', '\0' }
|
||||
|
||||
const end_or_symbol_or_comment_or_passthrough = symbolStart + end_or_comment + passthrough_start
|
||||
|
||||
|
||||
proc abortAsmParse (err:string) =
|
||||
#
|
||||
|
||||
let codeLen = code.len
|
||||
#let codeEnd = codeLen-1
|
||||
cpp.add asmx64pre
|
||||
|
||||
#log "{$1}\n" % [code]
|
||||
|
||||
type asmParseState = enum leading, mnemonic, betweenArguments, arguments, endCmd, skipToEndOfLine
|
||||
|
||||
var state:asmParseState = leading
|
||||
|
||||
proc checkEnd (err:string) =
|
||||
let ch = code [start]
|
||||
if int (ch) == 0:
|
||||
abortAsmParse (err)
|
||||
|
||||
proc get_passthrough () =
|
||||
inc start
|
||||
let prev_start = start
|
||||
let prev_token = token
|
||||
start += code.parseUntil (token, passthrough_end, start)
|
||||
checkEnd ("Failed to find passthrough end delimiter from offset $1 for:$2\n$3" % [$prev_start, $(code [prev_start-prev_token.len..prev_start]), token[1..token.len-1]])
|
||||
inc start
|
||||
cpp.add "`"
|
||||
cpp.add token
|
||||
cpp.add "`"
|
||||
|
||||
var inparse = true
|
||||
|
||||
proc checkCmdEnd () =
|
||||
if codeLen == start:
|
||||
state = endCmd
|
||||
inparse = false
|
||||
|
||||
while inparse:
|
||||
checkCmdEnd ()
|
||||
|
||||
log ("state=$1 start=$2" % [$state, $start])
|
||||
|
||||
case state:
|
||||
of leading:
|
||||
|
||||
echo "b100 ", start
|
||||
start += code.skipWhile (leadingWhiteSpace, start)
|
||||
echo "b200 ", start
|
||||
let ch = code [start]
|
||||
if ch in endOfLine:
|
||||
inc (line)
|
||||
#echo "c100 ", start, ' ', code
|
||||
start += code.skipWhile (endOfline, start)
|
||||
#echo "c200 ", start, ' ', code
|
||||
continue
|
||||
elif ch in symbolStart:
|
||||
state = mnemonic
|
||||
elif ch in eolComment:
|
||||
state = skipToEndOfLine
|
||||
elif ch in passthrough_start:
|
||||
get_passthrough ()
|
||||
echo "d100 ", start
|
||||
start += code.parseUntil (token, end_or_symbol_or_comment_or_passthrough, start)
|
||||
echo "d200 ", start
|
||||
cpp.add token
|
||||
state = mnemonic
|
||||
elif int (ch) == 0:
|
||||
break
|
||||
else:
|
||||
abortAsmParse ("after '$3' illegal character at offset $1: $2" % [$start, $(int (ch)), token])
|
||||
|
||||
of mnemonic:
|
||||
echo "e100 ", start
|
||||
start += code.parseWhile (token, symbol, start)
|
||||
echo "e200 ", start
|
||||
cpp.add xp
|
||||
cpp.add token
|
||||
cpp.add "("
|
||||
state = betweenArguments
|
||||
|
||||
of betweenArguments:
|
||||
let tmp = start
|
||||
let rcode = code
|
||||
start += rcode.parseUntil (token, end_or_symbol_or_comment_or_passthrough, tmp)
|
||||
cpp.add token
|
||||
|
||||
if codeLen <= start:
|
||||
state = endCmd
|
||||
continue
|
||||
|
||||
let ch = code [start]
|
||||
if ch in passthrough_start:
|
||||
get_passthrough ()
|
||||
continue
|
||||
if (ch in {'x', 'X'}) and ('0' == code [start-1]):
|
||||
token = $(code [start])
|
||||
cpp.add token
|
||||
inc start
|
||||
continue
|
||||
state = arguments
|
||||
|
||||
of arguments:
|
||||
if code [start] in end_or_comment:
|
||||
state = endCmd
|
||||
continue
|
||||
start += code.parseWhile (token, symbol, start)
|
||||
cpp.add xp
|
||||
cpp.add token
|
||||
state = betweenArguments
|
||||
|
||||
of endCmd:
|
||||
cpp.add ");\n"
|
||||
state = skipToEndOfLine
|
||||
|
||||
of skipToEndOfLine:
|
||||
echo "a100 ", start
|
||||
start += code.skipUntil (endOfLine, start)
|
||||
echo "a200 ", start
|
||||
start += code.skipWhile (endOfline, start)
|
||||
echo "a300 ", start
|
||||
inc line
|
||||
state = leading
|
||||
|
||||
cpp.add asmx64post
|
||||
|
||||
echo ($cpp)
|
||||
|
||||
macro asmx64x (code_in:expr) : stmt =
|
||||
code = $code_in
|
||||
echo ("code.len = $1, code = >>>$2<<<" % [$code.len, code])
|
||||
asmx64 ()
|
||||
discard result
|
||||
|
||||
asmx64x """
|
||||
mov rax, {m}
|
||||
ret
|
||||
"""
|
||||
|
|
@ -2,18 +2,19 @@ discard """
|
|||
msg: '''2
|
||||
3
|
||||
4:2
|
||||
'''
|
||||
Got Hi
|
||||
Got Hey'''
|
||||
"""
|
||||
|
||||
# bug #404
|
||||
|
||||
import macros, tables
|
||||
import macros, tables, strtabs
|
||||
|
||||
var ZOOT{.compileTime.} = initTable[int, int](2)
|
||||
var iii {.compiletime.} = 1
|
||||
|
||||
macro zoo:stmt=
|
||||
zoot[iii] = iii*2
|
||||
ZOOT[iii] = iii*2
|
||||
inc iii
|
||||
echo iii
|
||||
|
||||
|
|
@ -29,9 +30,7 @@ tupleUnpack
|
|||
|
||||
# bug #903
|
||||
|
||||
import strtabs
|
||||
|
||||
var x {.compileTime.}: PStringTable
|
||||
var x {.compileTime.}: StringTableRef
|
||||
|
||||
macro addStuff(stuff, body: expr): stmt {.immediate.} =
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue