aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-02-01 16:49:55 +0100
committerDrahflow <drahflow@gmx.de>2013-02-01 16:49:55 +0100
commitff9524395821632b35481009e20504382c66b64e (patch)
tree85e81f05aefa2619d64cd9d2e352a87ef9917da0
parent5c1b00b476b3fed6852426c2d3535848a1c68aef (diff)
io.ey
* syscalls * minimal string library * compiled client library * file handling
-rwxr-xr-xcompiler/elymas.ey13
-rw-r--r--compiler/elymasAsm.ey12
-rw-r--r--compiler/elymasAsmLib.ey23
-rw-r--r--compiler/elymasGlobal.ey73
-rw-r--r--compiler/elymasGlobalStr.ey109
-rw-r--r--compiler/elymasGlobalSys.ey13
-rw-r--r--compiler/elymasGlobalSysAsm.ey112
-rw-r--r--compiler/elymasLexer.ey5
-rw-r--r--compiler/standardClient.ey58
l---------examples/working-compiler/elymasLexer.ey1
-rw-r--r--examples/working-compiler/syscall.test (renamed from examples/working-compiler/syscall.ey)0
-rw-r--r--examples/working/strcat.ey2
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