diff options
| author | Drahflow <drahflow@gmx.de> | 2013-02-01 16:49:55 +0100 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2013-02-01 16:49:55 +0100 |
| commit | ff9524395821632b35481009e20504382c66b64e (patch) | |
| tree | 85e81f05aefa2619d64cd9d2e352a87ef9917da0 | |
| parent | 5c1b00b476b3fed6852426c2d3535848a1c68aef (diff) | |
io.ey
* syscalls
* minimal string library
* compiled client library
* file handling
| -rwxr-xr-x | compiler/elymas.ey | 13 | ||||
| -rw-r--r-- | compiler/elymasAsm.ey | 12 | ||||
| -rw-r--r-- | compiler/elymasAsmLib.ey | 23 | ||||
| -rw-r--r-- | compiler/elymasGlobal.ey | 73 | ||||
| -rw-r--r-- | compiler/elymasGlobalStr.ey | 109 | ||||
| -rw-r--r-- | compiler/elymasGlobalSys.ey | 13 | ||||
| -rw-r--r-- | compiler/elymasGlobalSysAsm.ey | 112 | ||||
| -rw-r--r-- | compiler/elymasLexer.ey | 5 | ||||
| -rw-r--r-- | compiler/standardClient.ey | 58 | ||||
| l--------- | examples/working-compiler/elymasLexer.ey | 1 | ||||
| -rw-r--r-- | examples/working-compiler/syscall.test (renamed from examples/working-compiler/syscall.ey) | 0 | ||||
| -rw-r--r-- | examples/working/strcat.ey | 2 |
12 files changed, 412 insertions, 9 deletions
diff --git a/compiler/elymas.ey b/compiler/elymas.ey index 5d1ca63..11a4d33 100755 --- a/compiler/elymas.ey +++ b/compiler/elymas.ey @@ -4,7 +4,16 @@ "elymasGlobal.ey" include "elymasLexer.ey" include -0 sys .argv _ len not { "Usage: ./elymas <input file.ey>" die } rep - * sys .file -010 .open executeFile +sys .argv len not { "Usage: ./elymas <input file.ey>" die } rep + +[ + "standard.ey" + "standardClient.ey" + 0 sys .argv * +] { + sys .file -0010 .open + executeFile + .close +} each # vim: syn=elymas diff --git a/compiler/elymasAsm.ey b/compiler/elymasAsm.ey index 5d28e96..bf55a51 100644 --- a/compiler/elymasAsm.ey +++ b/compiler/elymasAsm.ey @@ -551,6 +551,18 @@ scale idx mem sib } /leaqMemIndexScaleReg deff + { ==reg ==mem ==idx ==scale ==disp + reg bit64assert + mem bit64assert + idx bit64assert + + 1 reg idx mem rex + %8D + reg /sib modrm01 + scale idx mem sib + disp imm8 + } /leaqMemIndexScaleDisp8Reg deff + { ==mem ==i mem bit64assert i 256 lt assert diff --git a/compiler/elymasAsmLib.ey b/compiler/elymasAsmLib.ey index 0c9c039..f1f64a8 100644 --- a/compiler/elymasAsmLib.ey +++ b/compiler/elymasAsmLib.ey @@ -339,6 +339,29 @@ :retn ] /internalAllocateArray defv + + # allocate string, holding rdi bytes + # rdi -> expected number of bytes + # rax <- address of string on the heap + [ + /rdi :pushqReg + + /rdi :decqReg + 3 /rdi :shrqImm8Reg + 4 /rdi :addqImm8Reg + 3 /rdi :shlqImm8Reg + internalAllocate /rax :movqImmReg + /rax :callqReg + + # set type + %10 7 /rax :orbImmMemDisp8 + + /rdx /rdx :xorqRegReg + /rdx 8 /rax :movqRegMemDisp8 + 16 /rax :popqMemDisp8 + + :retn + ] /internalAllocateString defv > { defv }' allocateOffsetStruct { ==str diff --git a/compiler/elymasGlobal.ey b/compiler/elymasGlobal.ey index d9c8524..25b423f 100644 --- a/compiler/elymasGlobal.ey +++ b/compiler/elymasGlobal.ey @@ -637,8 +637,10 @@ %70 /cl :cmpbImmReg /arrayCat :jeLbl8 %10 /cl :cmpbImmReg - /stringCat :jeLbl8 + /unknownType :jneLbl8 + /stringCat :jmpLbl32 + @unknownType "neither string nor array in cat" ::outputError :ud2 @@ -681,14 +683,43 @@ 16 /r15 :addqImm8Reg /done :jmpLbl8 - @stringCat - # TODO - :ud2 - @mismatch "type mismatch in cat" ::outputError :ud2 + @stringCat + /rbx :popqReg + + 7 /rbx /cl :movbMemDisp8Reg + %F0 /cl :andbImmReg + %10 /cl :cmpbImmReg + /mismatch :jneLbl8 + + 16 /r15 :subqImm8Reg + /rax /r15 :movqRegMem + /rbx 8 /r15 :movqRegMemDisp8 # store + + 16 /rax /rdi :movqMemDisp8Reg + 16 /rbx /rdi :addqMemDisp8Reg + + ::internalAllocateString /rax :movqImmReg + /rax :callqReg + /rax :pushqReg + + 24 /rax /rdi :leaqMemDisp8Reg + + 8 /r15 /rbx :movqMemDisp8Reg + 16 /rbx /rcx :movqMemDisp8Reg + 24 /rbx /rsi :leaqMemDisp8Reg + :reprcx :movsb + + /r15 /rbx :movqMemReg + 16 /rbx /rcx :movqMemDisp8Reg + 24 /rbx /rsi :leaqMemDisp8Reg + :reprcx :movsb + + 16 /r15 :addqImm8Reg + @done /r15 :pushqMem 8 /r15 :addqImm8Reg @@ -813,6 +844,16 @@ :retn ] /ey> defv + + # die + # 0 -> object explaining what went wrong + [ + /rbx :popqReg + /rdi :popqReg + ::internalDumpErrorString /rax :movqImmReg + /rax :callqReg + :ud2 + ] /eydie defv > _ ==globalFunctions { defv }' ::allocateOffsetStruct < @@ -1597,6 +1638,27 @@ } each } /createScopeEntries deff + { + [ /eydefv /eydeff /eydefq ] { ==name + # create function + name | 8 sub /rdi :movqImmReg # adjust for expected (but non-existent) code block header size + ::currentScope /rsi :movqImmReg + /rsi /rsi :movqMemReg + /rdx /rdx :xorqRegReg # untyped + + ::internalAllocateFunction /rax :movqImmReg + /rax :callqReg + /rax :pushqReg + + # create string + name "ey(.*)" regex assert ::constStringCode _ len dearray + + # enter into current scope + |eydeff /rax :movqImmReg + /rax :callqReg + } each + } /createScopeExtensionEntries deff + [ globalFunctions keys len globalFunctions2 keys len add @@ -1648,6 +1710,7 @@ } /leaveSubScope deff "elymasGlobalSys.ey" include + "elymasGlobalStr.ey" include > /global defv # vim: syn=elymas diff --git a/compiler/elymasGlobalStr.ey b/compiler/elymasGlobalStr.ey new file mode 100644 index 0000000..299d880 --- /dev/null +++ b/compiler/elymasGlobalStr.ey @@ -0,0 +1,109 @@ +< + "str" enterSubScope + + < + # allocate an uninitialized string + # 0 -> number of data bytes to allocate + # 0 <- the string + [[ + /rbx :popqReg + + /rdi :popqReg + /rdi :pushqReg + + 8 /rdi /rdi :movqMemDisp8Reg + 24 /rdi :addqImm8Reg + ::internalAllocate /rax :movqImmReg + /rax :callqReg + + # set type + %10 7 /rax :orbImmMemDisp8 + + # clear hash value + /rdx /rdx :xorqRegReg + /rdx 8 /rax :movqRegMemDisp8 + + # set exact length + 16 /rax :popqMemDisp8 + + /rax :pushqReg + + /rbx :pushqReg + :retn + ]] /eyalloc defv + + # reduce exact string length in place + # 0 -> string to shorten + # 1 -> length of prefix + # 0 <- the same string (but now with exact length field overwritten) + # this effectively creates a prefix of the string + [[ + /rbx :popqReg + + /rax :popqReg + /rcx :popqReg + 8 /rcx /rcx :movqMemDisp8Reg + + 16 /rax /rcx :cmpqMemDisp8Reg + /ok :jbeLbl8 + + "prefix length above string length in inplacePrefix" ::outputError + :ud2 + + @ok + /rcx 16 /rax :movqRegMemDisp8 + + /rcx /rcx :xorqRegReg + /rcx 8 /rax :movqRegMemDisp8 # reset hash value + + /rax :pushqReg + + /rbx :pushqReg + :retn + ]] /eyinplacePrefix defv + + # calculate a string postfix + # TODO: correctly handly negative indices + # 0 -> string to shorten + # 1 -> position of string where to start the postfix + # 0 <- the requested postfix of the string + [[ + /rbx :popqReg + + /rax :popqReg + /rcx :popqReg + + /rax :pushqReg + + 16 /rax /rdi :movqMemDisp8Reg + 8 /rcx /rdi :subqMemDisp8Reg + /rdi :pushqReg + + ::internalAllocateString /rax :movqImmReg + /rax :callqReg + + /rcx :popqReg + /rsi :popqReg + /rax :pushqReg # store target string on stack + + 16 /rsi /rdx :movqMemDisp8Reg + /rcx /rdx :subqRegReg + + 24 1 /rdx /rsi /rsi :leaqMemIndexScaleDisp8Reg + 24 /rax /rdi :leaqMemDisp8Reg + :reprcx :movsb + + /rbx :pushqReg + :retn + ]] /eypostfix defv + > _ ==globalFunctions { defv }' ::allocateOffsetStruct + + [ + globalFunctions keys eydeff { | }' createScopeEntries + createScopeExtensionEntries + ] :execute + + leaveSubScope +> -- + +# vim: syn=elymas diff --git a/compiler/elymasGlobalSys.ey b/compiler/elymasGlobalSys.ey new file mode 100644 index 0000000..3a7be17 --- /dev/null +++ b/compiler/elymasGlobalSys.ey @@ -0,0 +1,13 @@ +< + "sys" enterSubScope + + [ + createScopeExtensionEntries + ] :execute + + "elymasGlobalSysAsm.ey" include + + leaveSubScope +> -- + +# vim: syn=elymas diff --git a/compiler/elymasGlobalSysAsm.ey b/compiler/elymasGlobalSysAsm.ey new file mode 100644 index 0000000..7bb79f6 --- /dev/null +++ b/compiler/elymasGlobalSysAsm.ey @@ -0,0 +1,112 @@ +< + < + # read absolute address + # 0 -> address to read + # 0 <- byte read + [[ + /rbx :popqReg + + 16 /rdi :movqImmReg + ::internalAllocate /rax :movqImmReg + /rax :callqReg + + /rcx :popqReg + /rax :pushqReg + + 8 /rcx /rcx :movqMemDisp8Reg + /rcx /rcx :movzxMem8Reg64 + /rcx 8 /rax :movqRegMemDisp8 + + /rbx :pushqReg + :retn + ]] /eypeek defv + + # write absolute address + # 0 -> address to write + # 1 -> value to write + [[ + /rbx :popqReg + + /rax :popqReg + 8 /rax /rax :movqMemDisp8Reg + /rcx :popqReg + 8 /rcx /rcx :movqMemDisp8Reg + /cl /rax :movbRegMem + + /rbx :pushqReg + :retn + ]] /eypoke defv + + # conduct a syscall + # 0 -> syscall number, rax before entry + # 1 -> rdi before entry + # 2 -> rsi before entry + # 3 -> rdx before entry + # 4 -> r10 before entry + # 5 -> r8 before entry + # 6 -> r9 before entry + # 0 <- rdx after syscall + # 1 <- rax after syscall + [[ + 8 /r15 :subqImm8Reg + /r15 :popqMem + + 2 { + 16 /rdi :movqImmReg + ::internalAllocate /rax :movqImmReg + /rax :callqReg + + 8 /r15 :subqImm8Reg + /rax /r15 :movqRegMem + } rep # allocate return integers + + [ /rax /r9 /r8 /r10 /rdx /rsi /rdi ] { ==reg + reg :popqReg + 7 reg /bl :movbMemDisp8Reg + %F0 /bl :andbImmReg + /intLoad reg cat :jzLbl8 + %10 /bl :cmpbImmReg + /stringLoad reg cat :jeLbl8 + + "neither int nor string argument in sys .asm .syscall" ::outputError + :ud2 + + /stringLoad reg cat :label + 24 reg reg :leaqMemDisp8Reg + /doneLoad reg cat :jmpLbl8 + + /intLoad reg cat :label + 8 reg reg :movqMemDisp8Reg + + /doneLoad reg cat :label + } each + + :syscall + + /r15 /rcx :movqMemReg + /rax 8 /rcx :movqRegMemDisp8 + /rcx :pushqReg + 8 /r15 :addqImm8Reg + + /r15 /rcx :movqMemReg + /rdx 8 /rcx :movqRegMemDisp8 + /rcx :pushqReg + 8 /r15 :addqImm8Reg + + /r15 :pushqMem + 8 /r15 :addqImm8Reg + :retn + ]] /eysyscall defv + > _ ==globalFunctions { defv }' ::allocateOffsetStruct + + "asm" enterSubScope + + [ + globalFunctions keys eydeff { | }' createScopeEntries + createScopeExtensionEntries + ] :execute + + leaveSubScope +> -- + +# vim: syn=elymas diff --git a/compiler/elymasLexer.ey b/compiler/elymasLexer.ey index b86f0be..8c17d61 100644 --- a/compiler/elymasLexer.ey +++ b/compiler/elymasLexer.ey @@ -63,6 +63,7 @@ "^\\\\\\\\(.*)" { str "\\" cat =str } strparse "^\\\\n(.*)" { str "\n" cat =str } strparse + "^\\\\0(.*)" { str "\0" cat =str } strparse "^\\\\\"(.*)" { str "\"" cat =str } strparse "^([^\"\\\\])(.*)" { str -01 cat =str } strparse strmatched not { "Tokenization of string-like failed" die } rep @@ -83,10 +84,10 @@ } { { _ "([^\\n]*)\\n(.*)" regex } { -102 -- tokenize { _ .handle - assemblerLibrary .stackDump + # assemblerLibrary .stackDump # assemblerLibrary .globalScopeDump } each } loop - } loop + } loop -- } /executeFile deff # vim: syn=elymas diff --git a/compiler/standardClient.ey b/compiler/standardClient.ey new file mode 100644 index 0000000..c865a5e --- /dev/null +++ b/compiler/standardClient.ey @@ -0,0 +1,58 @@ +< + # TODO: handle EINTR correctly + + 0 _ ==RDONLY + 1 _ ==WRONLY + 2 _ ==RDWR + bor bor ==RWMASK + + 0 ==READ + 1 ==WRITE + 2 ==OPEN + 3 ==CLOSE + + { < ==mode ==flags ==fd < + { flags RWMASK bnot band RDONLY bor =flags } /readonly deff + { flags RWMASK bnot band WRONLY bor =flags } /writeonly deff + { flags RWMASK bnot band RDWR bor =flags } /readwrite deff + { ==path + fd 0 ge { "file already open" die } rep + path "\0" cat flags mode 0 0 0 OPEN sys .asm .syscall -- _ =fd + 0 lt { "cannot open " path cat die } rep + } /open deff + { + fd 0 0 0 0 0 CLOSE sys .asm .syscall -- + 0 lt { "bad things happened to your close call" die } rep + } /close deff + { ==count + fd 0 lt { "file not open" die } rep + count str .alloc ==buf + fd buf count 0 0 0 READ sys .asm .syscall -- _ + 0 lt { "read failed" die } rep + buf str .inplacePrefix + } /read deff + { ==buf + fd 0 lt { "file not open" die } rep + fd buf _ len 0 0 0 WRITE sys .asm .syscall -- _ + 0 lt { "write failed" die } rep + } /write deff + { ==buf + fd 0 lt { "file not open" die } rep + { buf len } { + fd buf _ len 0 0 0 WRITE sys .asm .syscall -- _ + 0 lt { "write failed" die } rep + buf str .postfix =buf + } loop + } /writeall deff + > > -- } /makefile deff + + { # 0777 = 511 + 1 neg RDONLY 511 makefile + } /file sys .deff + + 0 RDONLY 0 makefile /in sys .defv + 1 WRONLY 0 makefile /out sys .defv + 2 WRONLY 0 makefile /err sys .defv +> -- + +# vim: syn=elymas diff --git a/examples/working-compiler/elymasLexer.ey b/examples/working-compiler/elymasLexer.ey new file mode 120000 index 0000000..050f21f --- /dev/null +++ b/examples/working-compiler/elymasLexer.ey @@ -0,0 +1 @@ +../../compiler/elymasLexer.ey
\ No newline at end of file diff --git a/examples/working-compiler/syscall.ey b/examples/working-compiler/syscall.test index dec484a..dec484a 100644 --- a/examples/working-compiler/syscall.ey +++ b/examples/working-compiler/syscall.test diff --git a/examples/working/strcat.ey b/examples/working/strcat.ey new file mode 100644 index 0000000..c3c187a --- /dev/null +++ b/examples/working/strcat.ey @@ -0,0 +1,2 @@ +"abc" "def" cat +4 "abcdef" str .postfix die |
