146 lines
3.2 KiB
Text
146 lines
3.2 KiB
Text
def insns
|
|
|
|
func main { # "entry point returning int" pop
|
|
def insns filename
|
|
=args # "put arg array into args var" pop
|
|
args 0 aget =filename
|
|
|
|
# "Start compile" pop
|
|
filename _file compile
|
|
|
|
0
|
|
}
|
|
|
|
def ptr 0 =ptr
|
|
|
|
# "function to fail the compiler due to an oversight by isbpl devs" pop
|
|
func internal_error {
|
|
"internal_error\n" puts
|
|
# "arg is on stack, no need for variables etc" pop
|
|
"\n" strconcat puts
|
|
2 exit
|
|
}
|
|
|
|
func is_space {
|
|
# "each line: dup-d or-d -> or-d dup-d" pop
|
|
dup " " eq
|
|
swap dup "\n" eq or
|
|
swap dup "\r" eq or
|
|
swap dup "\t" eq or
|
|
swap dup "" eq or
|
|
# "dup-d or-d -> or-d dup-d -> or-d" pop
|
|
swap pop swap
|
|
}
|
|
|
|
func read_string {
|
|
def s "" =s
|
|
def insn
|
|
|
|
while { 1 } {
|
|
insns ptr aget =insn
|
|
|
|
}
|
|
}
|
|
|
|
# "function to read a block of insns" pop
|
|
func read_block {
|
|
insns ptr aget dup # "dup the insn for later use" pop ( "{" eq not if {
|
|
"ERROR: read_block called with invalid ptr" internal_error
|
|
} )
|
|
def insn =insn # "insn was dup'd" pop
|
|
|
|
insn is_space not if {
|
|
# "if the insn is anything useful" pop
|
|
insn 0 aget '"' eq if { read_string }
|
|
}
|
|
|
|
ptr dup ++ =ptr
|
|
}
|
|
|
|
func compile {
|
|
def file
|
|
def content
|
|
def i
|
|
def ln
|
|
def j
|
|
def c
|
|
=file
|
|
|
|
# "read & split content" pop
|
|
0 _char ( file flength ) anew "\n" strsplit =content
|
|
|
|
1 neg =i
|
|
# "preprocess string" pop
|
|
while { ( i 1 + =i ) ( i content alen lt ) } {
|
|
content i aget =ln
|
|
# "remove tabs/spaces" pop
|
|
while { ( ln 0 aget dup ) eq ' ' eq '\t' or } {
|
|
# "remove first character" pop
|
|
ln 1 ln alen strsub =ln
|
|
}
|
|
# "remove comments" pop
|
|
1 neg =j
|
|
while { ( j 1 + =j ) ( j ln alen lt ) } {
|
|
( ln j aget dup =c dup ) ( '\"' eq '\'' eq or ) if {
|
|
j 1 + =j
|
|
while { ( ln j aget dup =c dup ) ( '\"' eq '\'' eq or ) not } {
|
|
j ( c '\\' eq if { 2 } else { 1 } ) + =j
|
|
}
|
|
}
|
|
c '#' eq if {
|
|
ln 0 j strsub
|
|
1 stop
|
|
}
|
|
}
|
|
}
|
|
|
|
# "join content" pop
|
|
content " " strjoin " " strsplit =content
|
|
|
|
content 1 mkcode
|
|
}
|
|
|
|
func mkcode {
|
|
def allowfunc
|
|
def content
|
|
def definefunc
|
|
def level
|
|
def i
|
|
=allowfunc
|
|
=content
|
|
|
|
1 neg =i
|
|
0 dup =isnative
|
|
dup =funcname
|
|
dup =definefunc
|
|
dup =level
|
|
pop
|
|
while { ( i 1 + =i ) ( i content alen lt ) } {
|
|
content i aget =keyword
|
|
keyword "" eq not if {
|
|
allowfunc if {
|
|
funcname 0 eq not keyword "{" eq and if {
|
|
i ( content i 1 + content alen strsub 0 mkcode ) + =i
|
|
content i aget =keyword
|
|
2 stop
|
|
}
|
|
definefunc if {
|
|
keyword =funcname
|
|
}
|
|
keyword "func" eq =definefunc
|
|
keyword "native" eq =native
|
|
}
|
|
keyword '{' if { level 1 + =level }
|
|
keyword '}' if { level 1 - =level }
|
|
keyword 'if' if {
|
|
}
|
|
}
|
|
level 1 neg eq if { 1 stop }
|
|
}
|
|
|
|
i
|
|
}
|
|
|
|
func append {
|
|
cmp swap "\n" strconcat strconcat =cmp
|
|
}
|