Improved bytecode output when calling a locally defined lambda.
This commit is contained in:
parent
e1f72a08ba
commit
5b508bf75c
229
tigerscheme.tig
229
tigerscheme.tig
|
@ -13,6 +13,8 @@ let /* Booleans */
|
||||||
var DEBUG_PRINT_TAPE : bool := false
|
var DEBUG_PRINT_TAPE : bool := false
|
||||||
var DEBUG_PRINT_PARSED : bool := false
|
var DEBUG_PRINT_PARSED : bool := false
|
||||||
var DEBUG_PRINT_JUMPS : bool := false
|
var DEBUG_PRINT_JUMPS : bool := false
|
||||||
|
var DEBUG_PRINT_MACRO : bool := true
|
||||||
|
var DEBUG_SHOW_FULL_ENVIRONMENT : bool := false
|
||||||
|
|
||||||
var ALLOW_TAPE_RESIZE : bool := true
|
var ALLOW_TAPE_RESIZE : bool := true
|
||||||
|
|
||||||
|
@ -116,11 +118,14 @@ let /* Booleans */
|
||||||
type pos = { at_char: int, line_num: int }
|
type pos = { at_char: int, line_num: int }
|
||||||
function new_pos (line_num: int, at_char: int): pos =
|
function new_pos (line_num: int, at_char: int): pos =
|
||||||
pos { at_char = at_char, line_num = line_num }
|
pos { at_char = at_char, line_num = line_num }
|
||||||
function line_num (pos: pos): int = pos.line_num
|
function line_num (pos: pos): int =
|
||||||
|
if pos <> nil
|
||||||
|
then pos.line_num
|
||||||
|
else -3
|
||||||
function at_char (pos: pos): int =
|
function at_char (pos: pos): int =
|
||||||
if pos <> nil
|
if pos <> nil
|
||||||
then pos.at_char
|
then pos.at_char
|
||||||
else -1
|
else -3
|
||||||
|
|
||||||
function pos_delta_char (pos: pos, delta: int): pos =
|
function pos_delta_char (pos: pos, delta: int): pos =
|
||||||
new_pos( line_num(pos)
|
new_pos( line_num(pos)
|
||||||
|
@ -128,9 +133,12 @@ let /* Booleans */
|
||||||
|
|
||||||
var pos_unknown : pos := new_pos(-1, -1)
|
var pos_unknown : pos := new_pos(-1, -1)
|
||||||
var pos_preamble: pos := new_pos(-2, -2)
|
var pos_preamble: pos := new_pos(-2, -2)
|
||||||
|
var pos_bad : pos := new_pos(-3, -3)
|
||||||
|
|
||||||
function pos_to_string (pos: pos): string =
|
function pos_to_string (pos: pos): string =
|
||||||
if pos = pos_unknown
|
if pos <> nil
|
||||||
|
then "no position"
|
||||||
|
else if pos = pos_unknown
|
||||||
then "unknown position"
|
then "unknown position"
|
||||||
else if pos = pos_preamble
|
else if pos = pos_preamble
|
||||||
then "preamble"
|
then "preamble"
|
||||||
|
@ -403,6 +411,13 @@ let /* Booleans */
|
||||||
& b.typ = type_integer
|
& b.typ = type_integer
|
||||||
& a.val_i = b.val_i
|
& a.val_i = b.val_i
|
||||||
|
|
||||||
|
function scheme_value_is_proper_list (ls: scheme_value): bool =
|
||||||
|
if ls = nil
|
||||||
|
then false
|
||||||
|
else ls.typ = type_nil
|
||||||
|
| ls.typ = type_pair
|
||||||
|
& scheme_value_is_proper_list(ls.val_cdr)
|
||||||
|
|
||||||
/* evq? See for definition:
|
/* evq? See for definition:
|
||||||
* https://people.csail.mit.edu/jaffer/r5rs/Equivalence-predicates.html
|
* https://people.csail.mit.edu/jaffer/r5rs/Equivalence-predicates.html
|
||||||
* */
|
* */
|
||||||
|
@ -594,7 +609,9 @@ let /* Booleans */
|
||||||
|
|
||||||
function parse_rec (): sexp_ast =
|
function parse_rec (): sexp_ast =
|
||||||
( ignore_ws()
|
( ignore_ws()
|
||||||
; if is_symbol(index)
|
; if index >= size(str)
|
||||||
|
then (parse_error("Reached end of string"); nil)
|
||||||
|
else if is_symbol(index)
|
||||||
then let var start_pos := new_pos(line_number, index)
|
then let var start_pos := new_pos(line_number, index)
|
||||||
in while index < size(str) & is_symbol(index)
|
in while index < size(str) & is_symbol(index)
|
||||||
do index := index + 1
|
do index := index + 1
|
||||||
|
@ -726,7 +743,9 @@ let /* Booleans */
|
||||||
; print("\n")
|
; print("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
in parse_rec()
|
in if size(str) > 0
|
||||||
|
then parse_rec()
|
||||||
|
else (parse_error("Nothing to parse. Given string empty!"); nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
/**** Instructions ****/
|
/**** Instructions ****/
|
||||||
|
@ -781,6 +800,7 @@ let /* Booleans */
|
||||||
var OPCODE_EXIT := 27
|
var OPCODE_EXIT := 27
|
||||||
var OPCODE_EQV := 28
|
var OPCODE_EQV := 28
|
||||||
var OPCODE_CONCAT := 29
|
var OPCODE_CONCAT := 29
|
||||||
|
var OPCODE_FORGET := 32
|
||||||
|
|
||||||
var OPCODE_DEBUG := 31
|
var OPCODE_DEBUG := 31
|
||||||
|
|
||||||
|
@ -821,6 +841,7 @@ let /* Booleans */
|
||||||
; code(OPCODE_RET, "RET", 1, 0, 0)
|
; code(OPCODE_RET, "RET", 1, 0, 0)
|
||||||
|
|
||||||
; code(OPCODE_DEF, "DEF", 0, 1, 0)
|
; code(OPCODE_DEF, "DEF", 0, 1, 0)
|
||||||
|
; code(OPCODE_FORGET, "FORGET", 1, 0, 0)
|
||||||
; code(OPCODE_SETG, "SETG", 0, 1, 0)
|
; code(OPCODE_SETG, "SETG", 0, 1, 0)
|
||||||
; code(OPCODE_DEFFUN, "DEFFUN", 1, 0, 0)
|
; code(OPCODE_DEFFUN, "DEFFUN", 1, 0, 0)
|
||||||
; code(OPCODE_POP, "POP", 0, 0, 0)
|
; code(OPCODE_POP, "POP", 0, 0, 0)
|
||||||
|
@ -988,6 +1009,7 @@ let /* Booleans */
|
||||||
, pos_r = pos_r }))
|
, pos_r = pos_r }))
|
||||||
; ())
|
; ())
|
||||||
|
|
||||||
|
|
||||||
function app_insn2 (insns: vm_insn_list, opcode:int, arg3: scheme_value, pos_l: pos, pos_r: pos) =
|
function app_insn2 (insns: vm_insn_list, opcode:int, arg3: scheme_value, pos_l: pos, pos_r: pos) =
|
||||||
( concat_lists(insns, single_insn(vm_insn { opcode = opcode
|
( concat_lists(insns, single_insn(vm_insn { opcode = opcode
|
||||||
, arg1 = 0
|
, arg1 = 0
|
||||||
|
@ -1253,6 +1275,15 @@ let /* Booleans */
|
||||||
; stdfun("exit")
|
; stdfun("exit")
|
||||||
; app(OPCODE_EXIT, true, "")
|
; app(OPCODE_EXIT, true, "")
|
||||||
|
|
||||||
|
/* Misc??? */
|
||||||
|
; stdfun("symbol?")
|
||||||
|
; app(OPCODE_TYPEOF, 0, "")
|
||||||
|
; app2(OPCODE_PUSH, int_val(type_symbol))
|
||||||
|
; app(OPCODE_NUMEQ, 0, "")
|
||||||
|
; app(OPCODE_RET, 1, "")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; std_insns
|
; std_insns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1348,6 +1379,9 @@ let /* Booleans */
|
||||||
, value)
|
, value)
|
||||||
, env )
|
, env )
|
||||||
|
|
||||||
|
function env_pop(env: vm_env): vm_env =
|
||||||
|
env.val_cdr
|
||||||
|
|
||||||
function global_env_push (env: vm_env, key: string, value: vm_env_elem): vm_env =
|
function global_env_push (env: vm_env, key: string, value: vm_env_elem): vm_env =
|
||||||
let
|
let
|
||||||
in if env.val_car.val_s <> GLOBAL_ENV_SENTINEL
|
in if env.val_car.val_s <> GLOBAL_ENV_SENTINEL
|
||||||
|
@ -1728,6 +1762,17 @@ let /* Booleans */
|
||||||
; insns_car )
|
; insns_car )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function compile_load_of_arguments ( insns: vm_insn_list
|
||||||
|
, sexp_args: sexp_ast
|
||||||
|
, pos_l: pos
|
||||||
|
, pos_r: pos) =
|
||||||
|
if sexp_args = nil
|
||||||
|
| sexp_args.typ = type_nil
|
||||||
|
| sexp_args.val_car = nil
|
||||||
|
then ()
|
||||||
|
else ( compile_load_of_arguments(insns, sexp_args.val_cdr, pos_l, pos_r)
|
||||||
|
; app_insn(insns, OPCODE_DEF, 0, sexp_args.val_car.val_s, pos_l, pos_r) )
|
||||||
|
|
||||||
function compile_rec ( ast: sexp_ast
|
function compile_rec ( ast: sexp_ast
|
||||||
, can_tail_call: bool
|
, can_tail_call: bool
|
||||||
, expected_type: type_type ): vm_insn_list =
|
, expected_type: type_type ): vm_insn_list =
|
||||||
|
@ -1744,8 +1789,13 @@ let /* Booleans */
|
||||||
tail_position_one( atom_to_insn(ast, ast.pos_l, ast.pos_r, expected_type)
|
tail_position_one( atom_to_insn(ast, ast.pos_l, ast.pos_r, expected_type)
|
||||||
, can_tail_call)
|
, can_tail_call)
|
||||||
|
|
||||||
|
else if ast.val_car = nil
|
||||||
|
| ast.val_cdr = nil
|
||||||
|
then ( compile_error("Attemping to compile malformed ast", ast)
|
||||||
|
; nil )
|
||||||
|
|
||||||
/* If statements */
|
/* If statements */
|
||||||
else if ast.val_car <> nil
|
else if ast.val_car.typ = type_symbol
|
||||||
& ast.val_car.val_s = "if"
|
& ast.val_car.val_s = "if"
|
||||||
then let var insns_test := compile_rec(ast.val_cdr.val_car, false, type_any)
|
then let var insns_test := compile_rec(ast.val_cdr.val_car, false, type_any)
|
||||||
var insns_then := compile_rec(ast.val_cdr.val_cdr.val_car, can_tail_call, type_any)
|
var insns_then := compile_rec(ast.val_cdr.val_cdr.val_car, can_tail_call, type_any)
|
||||||
|
@ -1754,36 +1804,43 @@ let /* Booleans */
|
||||||
else tail_position_one( atom_to_insn(VALUE_UNSPECIFIED, ast.pos_l, ast.pos_r, 0)
|
else tail_position_one( atom_to_insn(VALUE_UNSPECIFIED, ast.pos_l, ast.pos_r, 0)
|
||||||
, can_tail_call)
|
, can_tail_call)
|
||||||
|
|
||||||
var jump_then := sexp_ast_length(insns_then) + 1
|
var jump_then := sexp_ast_length(insns_then) + 1 + (if can_tail_call then 0 else 1)
|
||||||
var jump_else := sexp_ast_length(insns_else) + 1 + 1
|
var jump_else := sexp_ast_length(insns_else) + 1
|
||||||
|
|
||||||
var pos_l := ast.pos_l
|
var pos_l := ast.pos_l
|
||||||
var pos_r := ast.pos_r
|
var pos_r := ast.pos_r
|
||||||
|
|
||||||
in app_insn(insns_test, OPCODE_CSKIP, 2, "" , pos_l, pos_r)
|
in app_insn(insns_test, OPCODE_CSKIP, jump_then, "" , pos_l, pos_r)
|
||||||
; app_insn(insns_test, OPCODE_DGOTO, jump_else, "" , pos_l, pos_r)
|
|
||||||
; concat_lists(insns_test, insns_else)
|
|
||||||
; app_insn(insns_test, OPCODE_DGOTO, jump_then, "" , pos_l, pos_r)
|
|
||||||
; concat_lists(insns_test, insns_then)
|
; concat_lists(insns_test, insns_then)
|
||||||
|
; if not(can_tail_call)
|
||||||
|
then app_insn(insns_test, OPCODE_DGOTO, jump_else, "" , pos_l, pos_r)
|
||||||
|
; concat_lists(insns_test, insns_else)
|
||||||
; insns_test
|
; insns_test
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Define statements */
|
/* Define statements */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "define"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "define"
|
||||||
then compile_define(ast)
|
then compile_define(ast)
|
||||||
|
|
||||||
/* Syntax define statements */
|
/* Syntax define statements */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "define-syntax"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "define-syntax"
|
||||||
then ( compile_error("Please do not compile define-syntax", ast)
|
then ( compile_error("Please do not compile define-syntax", ast)
|
||||||
; single_insn(atom_to_insn(VALUE_UNSPECIFIED, ast.pos_l, ast.pos_r, 0)))
|
; single_insn(atom_to_insn(VALUE_UNSPECIFIED, ast.pos_l, ast.pos_r, 0)))
|
||||||
|
|
||||||
|
|
||||||
/* Syntax rules expression */
|
/* Syntax rules expression */
|
||||||
|
/*
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "syntax-rules"
|
else if ast.val_car <> nil & ast.val_car.val_s = "syntax-rules"
|
||||||
then compile_syntax_rules(ast)
|
then compile_syntax_rules(ast)
|
||||||
|
*/
|
||||||
|
|
||||||
/* Begin expressions */
|
/* Begin expressions */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "begin"
|
/* TODO: Implement using macroes, when those are
|
||||||
|
* available. */
|
||||||
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "begin"
|
||||||
then let var insns := vm_insn_list { first = nil, last = nil }
|
then let var insns := vm_insn_list { first = nil, last = nil }
|
||||||
var head := ast.val_cdr
|
var head := ast.val_cdr
|
||||||
|
|
||||||
|
@ -1798,7 +1855,8 @@ let /* Booleans */
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Quote expressions */
|
/* Quote expressions */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "quote"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "quote"
|
||||||
then let var datum := ast.val_cdr.val_car
|
then let var datum := ast.val_cdr.val_car
|
||||||
|
|
||||||
in tail_position_one( vm_insn { opcode = OPCODE_PUSH
|
in tail_position_one( vm_insn { opcode = OPCODE_PUSH
|
||||||
|
@ -1811,7 +1869,8 @@ let /* Booleans */
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Quasi-Quote expressions */
|
/* Quasi-Quote expressions */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "quasiquote"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "quasiquote"
|
||||||
then let var datum := ast.val_cdr.val_car
|
then let var datum := ast.val_cdr.val_car
|
||||||
var insns := compile_quasiquote(datum)
|
var insns := compile_quasiquote(datum)
|
||||||
|
|
||||||
|
@ -1827,7 +1886,8 @@ let /* Booleans */
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Set statements */
|
/* Set statements */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "set!"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "set!"
|
||||||
then let var sym := ast.val_cdr.val_car.val_s
|
then let var sym := ast.val_cdr.val_car.val_s
|
||||||
var exp_insns := compile_rec(ast.val_cdr.val_cdr.val_car, false, type_any)
|
var exp_insns := compile_rec(ast.val_cdr.val_cdr.val_car, false, type_any)
|
||||||
|
|
||||||
|
@ -1837,46 +1897,30 @@ let /* Booleans */
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Lambda expressions */
|
/* Lambda expressions */
|
||||||
else if ast.val_car <> nil & ast.val_car.val_s = "lambda"
|
else if ast.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_s = "lambda"
|
||||||
|
|
||||||
then let var insns_body := compile_rec(ast.val_cdr.val_cdr.val_car, true, type_any)
|
then let var insns_body := compile_rec(ast.val_cdr.val_cdr.val_car, true, type_any)
|
||||||
|
|
||||||
var pos_l := ast.pos_l
|
var pos_l := ast.pos_l
|
||||||
var pos_r := ast.pos_r
|
var pos_r := ast.pos_r
|
||||||
|
|
||||||
function build_insns_arguments (args: sexp_ast, derp: vm_insn_list_link): vm_insn_list_link =
|
|
||||||
if args = nil
|
|
||||||
| args.typ = type_nil
|
|
||||||
| args.val_car = nil
|
|
||||||
then derp
|
|
||||||
else
|
|
||||||
build_insns_arguments( args.val_cdr
|
|
||||||
, vm_insn_list_link { insn = vm_insn { opcode = OPCODE_DEF
|
|
||||||
, arg1 = 0
|
|
||||||
, arg2 = args.val_car.val_s
|
|
||||||
, arg3 = nil
|
|
||||||
, pos_l = pos_l
|
|
||||||
, pos_r = pos_r }
|
|
||||||
, next = derp })
|
|
||||||
|
|
||||||
var insns_ass_args := list(build_insns_arguments(ast.val_cdr.val_car, nil))
|
|
||||||
|
|
||||||
var jump_lambda := sexp_ast_length(insns_body)
|
var jump_lambda := sexp_ast_length(insns_body)
|
||||||
+ sexp_ast_length(insns_ass_args)
|
+ sexp_list_length(ast.val_cdr.val_car)
|
||||||
+ 1
|
+ 1
|
||||||
|
|
||||||
var insns := vm_insn_list { first = nil, last = nil }
|
var insns := vm_insn_list { first = nil, last = nil }
|
||||||
|
|
||||||
in app_insn(insns, OPCODE_DEFFUN, 2, "", pos_l, pos_r)
|
in app_insn(insns, OPCODE_DEFFUN, 2, "", pos_l, pos_r)
|
||||||
; app_insn(insns, OPCODE_DGOTO, jump_lambda, "" , pos_l, pos_r)
|
; app_insn(insns, OPCODE_DGOTO, jump_lambda, "" , pos_l, pos_r)
|
||||||
; concat_lists(insns, insns_ass_args)
|
; compile_load_of_arguments(insns, ast.val_cdr.val_car, pos_l, pos_r)
|
||||||
; concat_lists(insns, insns_body)
|
; concat_lists(insns, insns_body)
|
||||||
; tail_position(insns, can_tail_call, ast.pos_l, ast.pos_r)
|
; tail_position(insns, can_tail_call, ast.pos_l, ast.pos_r)
|
||||||
; insns
|
; insns
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Macro applications */
|
/* Macro applications */
|
||||||
else if ast.val_car <> nil
|
else if ast.val_car.typ = type_symbol
|
||||||
& ast.val_car.typ = type_symbol
|
|
||||||
& ast.val_car.val_s <> ""
|
& ast.val_car.val_s <> ""
|
||||||
& env_seek_elem(env_macro, ast.val_car.val_s) <> nil
|
& env_seek_elem(env_macro, ast.val_car.val_s) <> nil
|
||||||
then let var stack := stack_new()
|
then let var stack := stack_new()
|
||||||
|
@ -1895,9 +1939,59 @@ let /* Booleans */
|
||||||
, ast)
|
, ast)
|
||||||
; TRIGGERED_EXIT := true
|
; TRIGGERED_EXIT := true
|
||||||
; nil )
|
; nil )
|
||||||
else ( vm_run(macro_tape, fun.val_i, stack, fun.val_car, "", env_global)
|
else let var derp: scheme_value := nil
|
||||||
/* TODO: Assert that there is something on the stack */
|
in vm_run(macro_tape, fun.val_i, stack, fun.val_car, "", env_global)
|
||||||
; compile_rec(stack_pop(stack), can_tail_call, type_any) )
|
; /* TODO: Assert that there is something on the stack */
|
||||||
|
derp := stack_pop(stack)
|
||||||
|
; if DEBUG_PRINT_MACRO
|
||||||
|
then ( print("Macro expanded to: ")
|
||||||
|
; print(value_to_string(derp))
|
||||||
|
; print("\n") )
|
||||||
|
; compile_rec(derp, can_tail_call, type_any)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
/* Call-lambda expressions: A system for binding local
|
||||||
|
* variables */
|
||||||
|
/* Lambda expressions */
|
||||||
|
else if ast.val_car.typ = type_pair
|
||||||
|
& ast.val_car.val_car.typ = type_symbol
|
||||||
|
& ast.val_car.val_car.val_s = "lambda"
|
||||||
|
|
||||||
|
/* Does not support non-proper lists, currently: */
|
||||||
|
& scheme_value_is_proper_list (ast.val_car.val_cdr.val_car)
|
||||||
|
then
|
||||||
|
let var pos_l := ast.pos_l
|
||||||
|
var pos_r := ast.pos_r
|
||||||
|
|
||||||
|
var insns := vm_insn_list { first = nil, last = nil }
|
||||||
|
|
||||||
|
var num_required_args := sexp_list_length (ast.val_car.val_cdr.val_car)
|
||||||
|
var num_given_args := sexp_list_length (ast.val_cdr)
|
||||||
|
/* TODO: Give error when numbers of arguments does
|
||||||
|
* not match */
|
||||||
|
|
||||||
|
var ast_iter := ast.val_cdr
|
||||||
|
|
||||||
|
in ()
|
||||||
|
|
||||||
|
/* First compile arguments onto stack */
|
||||||
|
; while ast_iter <> nil & ast_iter.typ = type_pair
|
||||||
|
do ( concat_lists(insns, compile_rec(ast_iter.val_car, false, type_any))
|
||||||
|
; ast_iter := ast_iter.val_cdr )
|
||||||
|
|
||||||
|
/* Then assign them to variables */
|
||||||
|
; print(concat(value_to_string(ast.val_car.val_cdr.val_car), "\n"))
|
||||||
|
; compile_load_of_arguments(insns, ast.val_car.val_cdr.val_car, pos_l, pos_r)
|
||||||
|
|
||||||
|
/* Perform body */
|
||||||
|
; concat_lists(insns, compile_rec(ast.val_car.val_cdr.val_cdr.val_car, can_tail_call, type_any))
|
||||||
|
|
||||||
|
/* Forget variables again */
|
||||||
|
; app_insn(insns, OPCODE_FORGET, num_required_args, "", pos_l, pos_r)
|
||||||
|
|
||||||
|
/* Return instructions */
|
||||||
|
; insns
|
||||||
end
|
end
|
||||||
|
|
||||||
/* Call expressions */
|
/* Call expressions */
|
||||||
|
@ -1926,8 +2020,8 @@ let /* Booleans */
|
||||||
end
|
end
|
||||||
|
|
||||||
function compile_error(errmsg: string, errast: sexp_ast) =
|
function compile_error(errmsg: string, errast: sexp_ast) =
|
||||||
let var repr_pos_l := pos_to_string(errast.pos_l)
|
let var repr_pos_l := pos_to_string(if errast = nil then nil else errast.pos_l)
|
||||||
var repr_pos_r := pos_to_string(errast.pos_r)
|
var repr_pos_r := pos_to_string(if errast = nil then nil else errast.pos_r)
|
||||||
in print("Tiger-scheme compile error\n ")
|
in print("Tiger-scheme compile error\n ")
|
||||||
; print(errmsg)
|
; print(errmsg)
|
||||||
; print("\n For scheme: ")
|
; print("\n For scheme: ")
|
||||||
|
@ -1940,8 +2034,12 @@ let /* Booleans */
|
||||||
; print("\n")
|
; print("\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
var base_insns := compile_rec(ast, false, type_any)
|
var base_insns :=
|
||||||
in app_insn (base_insns, OPCODE_EXIT, 0, "", ast.pos_l, ast.pos_r)
|
if ast = nil
|
||||||
|
then (compile_error("Given ast was nil!", ast); nil)
|
||||||
|
else compile_rec(ast, false, type_any)
|
||||||
|
in if ast <> nil
|
||||||
|
then app_insn (base_insns, OPCODE_EXIT, 0, "", ast.pos_l, ast.pos_r)
|
||||||
; base_insns
|
; base_insns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2163,9 +2261,12 @@ let /* Booleans */
|
||||||
if value = nil
|
if value = nil
|
||||||
then run_error(concat5( "Attempting to access unknown variable \""
|
then run_error(concat5( "Attempting to access unknown variable \""
|
||||||
, tape[ip].arg2
|
, tape[ip].arg2
|
||||||
, "\"\n Environment looks like "
|
, "\"\n"
|
||||||
, env_to_string(env)
|
, ""
|
||||||
, ""))
|
, if DEBUG_SHOW_FULL_ENVIRONMENT
|
||||||
|
then concat( "\tEnvironment looks like "
|
||||||
|
, env_to_string(env))
|
||||||
|
else ""))
|
||||||
else if tape[ip].arg1 <> 0
|
else if tape[ip].arg1 <> 0
|
||||||
& tape[ip].arg1 <> value.typ
|
& tape[ip].arg1 <> value.typ
|
||||||
then run_error(concat6( "Attempting to access variable \""
|
then run_error(concat6( "Attempting to access variable \""
|
||||||
|
@ -2185,6 +2286,11 @@ let /* Booleans */
|
||||||
; ip := ip + 1
|
; ip := ip + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else if tape[ip].opcode = OPCODE_FORGET
|
||||||
|
then ( for i := 1 to tape[ip].arg1
|
||||||
|
do env := env_pop(env)
|
||||||
|
; ip := ip + 1 )
|
||||||
|
|
||||||
else if tape[ip].opcode = OPCODE_SETG
|
else if tape[ip].opcode = OPCODE_SETG
|
||||||
then let var value := stack_pop(stack)
|
then let var value := stack_pop(stack)
|
||||||
var new_env := global_env_push(global_env, tape[ip].arg2, value)
|
var new_env := global_env_push(global_env, tape[ip].arg2, value)
|
||||||
|
@ -2450,14 +2556,26 @@ let /* Booleans */
|
||||||
let var depth := 0
|
let var depth := 0
|
||||||
var char := "BAD SHIT HAPPENED"
|
var char := "BAD SHIT HAPPENED"
|
||||||
var text := ""
|
var text := ""
|
||||||
|
var comment_mode := false
|
||||||
in while char <> ""
|
in while char <> ""
|
||||||
do ( char := getchar()
|
do ( char := getchar()
|
||||||
; text := concat(text, char)
|
; text := concat(text, char)
|
||||||
; if char = "("
|
; if comment_mode
|
||||||
|
& char = "\n"
|
||||||
|
then comment_mode := false
|
||||||
|
else if comment_mode
|
||||||
|
then () /* Do nothing */
|
||||||
|
|
||||||
|
/* We can assume that comment mode is not enabled for
|
||||||
|
* these: */
|
||||||
|
else if char = "("
|
||||||
then depth := depth + 1
|
then depth := depth + 1
|
||||||
else if char = ")"
|
else if char = ")"
|
||||||
then ( depth := depth - 1
|
then ( depth := depth - 1
|
||||||
; if depth = 0 then break ))
|
; if depth = 0 then break )
|
||||||
|
else if char = ";"
|
||||||
|
then comment_mode := true
|
||||||
|
)
|
||||||
; text
|
; text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2473,9 +2591,12 @@ in print("Ready for the scheming Tiger?\n")
|
||||||
|
|
||||||
var macro_name := "" /* Not macro is "" */
|
var macro_name := "" /* Not macro is "" */
|
||||||
|
|
||||||
var sexp := parse_string(text)
|
var sexp := if size(text) > 0
|
||||||
|
then parse_string(text)
|
||||||
|
else nil
|
||||||
var sexp_compile :=
|
var sexp_compile :=
|
||||||
if sexp.typ = type_pair
|
if sexp <> nil
|
||||||
|
& sexp.typ = type_pair
|
||||||
& sexp.val_car.typ = type_symbol
|
& sexp.val_car.typ = type_symbol
|
||||||
& sexp.val_car.val_s = "define-syntax"
|
& sexp.val_car.val_s = "define-syntax"
|
||||||
then ( macro_name := sexp.val_cdr.val_car.val_s
|
then ( macro_name := sexp.val_cdr.val_car.val_s
|
||||||
|
|
Loading…
Reference in New Issue
Block a user