isbpl/isbpl.isbpl

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
}