changeset eac58af6f029 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=eac58af6f029 user: Simon Forman <sform****@hushm*****> date: Thu Aug 22 15:45:24 2019 -0700 description: Using partial deduction to inline literals, functions, and combinators. changeset 388498a92ec2 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=388498a92ec2 user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 07:43:21 2019 -0800 description: Call for_serial/2 changeset 35adeef789b5 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=35adeef789b5 user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 07:53:21 2019 -0800 description: Definition of ii combinator. ii == [dip] dupdip i a [F] ii -------------- F a F changeset 279af86ad1c7 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=279af86ad1c7 user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 07:54:04 2019 -0800 description: Modify error reporting a lil; words word. changeset c6855764e56c in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=c6855764e56c user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 07:55:01 2019 -0800 description: Minor cleanup. changeset 9e81f11a3d9b in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=9e81f11a3d9b user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 14:57:41 2019 -0800 description: Take two on the compiler. changeset acb9fe43416f in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=acb9fe43416f user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 15:53:07 2019 -0800 description: A start on converting the mainloop. changeset b2193326aa4b in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=b2193326aa4b user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 16:15:41 2019 -0800 description: if_literal changeset 5f06141751b4 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=5f06141751b4 user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 16:28:28 2019 -0800 description: lookup changeset b3c77a3888a0 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=b3c77a3888a0 user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 17:25:04 2019 -0800 description: WIth push2 finished that's the mainloop converted. changeset 0efb54e09cea in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=0efb54e09cea user: Simon Forman <sform****@hushm*****> date: Thu Nov 07 20:21:26 2019 -0800 description: hmm... changeset fa99e0be2382 in joypy/Joypy details: http://hg.osdn.jp/view/joypy/Joypy?cmd=changeset;node=fa99e0be2382 user: Simon Forman <sform****@hushm*****> date: Fri Nov 08 08:08:53 2019 -0800 description: Just do it in asm. diffstat: joy/library.py | 1 + thun/TLA.pl | 4 - thun/compiler.markII.pl | 421 +++++++++++++++++++++++++++++++++++++++++ thun/compiler.pl | 3 +- thun/gnu-prolog/junk/partev.pl | 167 ++++++++++++++++ thun/markII.rst | 200 +++++++++++++++++++ thun/thun.pl | 12 +- 7 files changed, 802 insertions(+), 6 deletions(-) diffs (truncated from 895 to 300 lines): diff -r c745734dea14 -r fa99e0be2382 joy/library.py --- a/joy/library.py Tue Aug 20 22:00:27 2019 -0700 +++ b/joy/library.py Fri Nov 08 08:08:53 2019 -0800 @@ -206,6 +206,7 @@ definitions = ('''\ +ii == [dip] dupdip i of == swap at product == 1 swap [*] step flatten == [] swap [concat] step diff -r c745734dea14 -r fa99e0be2382 thun/TLA.pl --- a/thun/TLA.pl Tue Aug 20 22:00:27 2019 -0700 +++ b/thun/TLA.pl Fri Nov 08 08:08:53 2019 -0800 @@ -61,7 +61,6 @@ type_ok(Small, Big) :- Small in 0..3, Big in 0..5. - next_dh(Moves) :- next_dh(0, 0, Moves). next_dh(Small, Big, [[Move, Si, Bi]|Moves]) :- @@ -69,7 +68,6 @@ die_hard(Move, Small, Big, Si, Bi), (Bi = 4 -> Moves = [] ; next_dh(Si, Bi, Moves)). - die_hard( fill_small, Small, Big, 3, Big) :- Small #< 3. die_hard( fill_big, Small, Big, Small, 5) :- Big #< 5. die_hard(empty_small, Small, Big, 0, Big) :- Small #> 0. @@ -83,7 +81,6 @@ Small #< 3, Big #> 0, big_to_small(Small, Big, S, B). - big_to_small(Small, Big, S, 0) :- Small + Big #=< 3, S #= Small + Big. @@ -92,7 +89,6 @@ Small + Big #> 3, B #= Big - (3 - Small). - small_to_big(Small, Big, 0, B) :- Small + Big #=< 5, B #= Small + Big. diff -r c745734dea14 -r fa99e0be2382 thun/compiler.markII.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thun/compiler.markII.pl Fri Nov 08 08:08:53 2019 -0800 @@ -0,0 +1,421 @@ +/* + +Copyright © 2018-2019 Simon Forman + +This file is part of Thun + +Thun is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Thun is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Thun. If not see <http://www.gnu.org/licenses/>. + +Mark II + +*/ +:- use_module(library(assoc)). +:- use_module(library(clpfd)). + +% Just do it in assembler. + + +program([ % Mainloop. + + do_offset(Over), % Oberon bootloader writes MemLim to RAM[12] and + allocate(_, 16), % stackOrg to RAM[24], we don't need these + label(Over), % but they must not be allowed to corrupt our code. + + mov_imm(0, 0), % zero out the root cell. + store_word(0, 0, 0), + + mov_imm(SP, 0x1000), + mov_imm(EXPR_addr, 0x500), + mov_imm(TOS, 0), + mov_imm(TERM, 0), + store_word(TOS, SP, 0), % RAM[SP] := 0 + + label(Main), + + % if_zero(EXPR_addr, HALT), + sub_imm(EXPR_addr, EXPR_addr, 0), + eq_offset(HALT), + + % deref(EXPR_addr, EXPR), + load_word(EXPR, EXPR_addr, 0), % Load expr pair record into EXPR + + % At this point EXPR holds the record word of the expression. + + ror_imm(TermAddr, EXPR, -15), % put the offset in TermAddr + % No need to mask off high bits as the type tag for pairs is 00 + + add(TermAddr, TermAddr, EXPR_addr), + + % TermAddr has the address of the term record. + + load_word(TERM, TermAddr, 0), % Bring the record in from RAM. + + % Now Term has the term's record data and TermAddr has the address of the term. + + and_imm(TEMP0, EXPR, 0x7fff), % get the offset of the tail of the expr + eq_offset(Foo), % if the offset is zero don't add the adress. it's empty list. + add(TEMP0, TEMP0, EXPR_addr), % Add the address to the offset. + label(Foo), + mov(EXPR_addr, TEMP0), + + % EXPR_addr now holds the address of the next cell of the expression list. + + % if_literal(TERM, PUSH), + ror_imm(TEMP0, TERM, -30), % get just the two tag bits. + sub_imm(TEMP0, TEMP0, 2), % if this is a symbol result is zero. + ne_offset(PUSH), + + % if it is a symbol the rest of it is the pointer to the machine code. + % lookup(TERM), % Jump to command. + mov_imm_with_shift(TEMP0, 0x3fff), % TEMP0 = 0x3fffffff + ior_imm(TEMP0, TEMP0, 0xffff), + and(TEMP0, TEMP0, TERM), + eq(TEMP0), % double check that this works with pointer in reg... + + % going into push we have the term + label(PUSH), + % push2(TOS, TEMP1, SP), % stack = TERM, stack + + sub_imm(SP, SP, 4), % SP -= 1 (word, not byte) + % SP points to the future home of the new stack cell. + sub(TOS, TermAddr, SP), % TOS := &temp - sp + % TOS has the offset from new stack cell to term cell. + % Combine with the offset to the previous stack cell. + lsl_imm(TOS, TOS, 15), % TOS := TOS << 15 + ior(TOS, TOS, 4), % TOS := TOS | 4 + + % label(DONE), + store_word(TOS, SP, 0), % RAM[SP] := TOS + do_offset(Main), + label(HALT), + do_offset(HALT) + +]) :- [SP, EXPR_addr, TOS, TERM, EXPR, TermAddr, TEMP0]=[0, 1, 2, 3, 4, 5, 6]. + + + +do :- program(Program), + compile_program(Program, Binary), + write_binary('joy_asmii.bin', Binary). + + +compile_program(ASM, Binary) :- + phrase(linker(ASM), EnumeratedASM), + phrase(asm(EnumeratedASM), Binary). + + + +/* + +Linker + +*/ + +linker(ASM) --> enumerate_asm(ASM, 0, _). + +enumerate_asm( [], N, N) --> !, []. +enumerate_asm( [Term|Terms], N, M) --> !, enumerate_asm(Term, N, O), enumerate_asm(Terms, O, M). +enumerate_asm( label(N) , N, N) --> !, []. +enumerate_asm(allocate(N, Bytes), N, M) --> !, {Bits is 8 * Bytes}, [skip(Bits)], {align(N, Bytes, M)}. +enumerate_asm( Instr, N, M) --> [(Z, Instr)], {align(N, 0, Z), align(Z, 4, M)}. + +align(_, Bytes, _) :- (Bytes < 0 -> write('Align negative number? No!')), !, fail. +align(N, 1, M) :- !, M is N + 1. +align(N, Bytes, M) :- N mod 4 =:= 0, !, M is N + Bytes. +align(N, Bytes, M) :- Padding is 4 - (N mod 4), M is N + Bytes + Padding. + + +/* + +Assembler + +*/ + +asm([]) --> !, []. +asm([ skip(Bits)|Rest]) --> !, skip(Bits), asm(Rest). +asm([(N, Instruction)|Rest]) --> !, asm(N, Instruction), asm(Rest). + +asm(_, expr_cell(Func, NextCell)) --> !, + {Data is (Func << 16) \/ NextCell}, asm(_, word(Data)). + +asm(_, word(Word)) --> !, {binary_number(Bits, Word)}, collect(32, Bits). + +asm(_, load_word(A, B, Offset)) --> !, instruction_format_F2(0, 0, A, B, Offset). +asm(_, load_byte(A, B, Offset)) --> !, instruction_format_F2(0, 1, A, B, Offset). +asm(_, store_word(A, B, Offset)) --> !, instruction_format_F2(1, 0, A, B, Offset). +asm(_, store_byte(A, B, Offset)) --> !, instruction_format_F2(1, 1, A, B, Offset). + +asm(_, mov(A, C)) --> instruction_format_F0(0, A, 0, mov, C). +asm(_, mov_with_shift(A, C)) --> instruction_format_F0(1, A, 0, mov, C). + +asm(_, mov_imm_with_shift(A, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(1, 0, A, 0, mov, Imm). +asm(_, mov_imm_with_shift(A, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(1, 0, A, 0, mov, Imm). +asm(_, mov_imm_with_shift(_, _)) --> {write('Immediate value out of bounds'), fail}. + +asm(_, mov_imm(A, Imm) ) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, 0, mov, Imm). +asm(_, mov_imm(A, Imm) ) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, 0, mov, Imm). +asm(_, mov_imm(_, _) ) --> {write('Immediate value out of bounds'), fail}. + +asm(_, add(A, B, C)) --> instruction_format_F0(0, A, B, add, C). +asm(_, add_carry(A, B, C)) --> instruction_format_F0(1, A, B, add, C). +asm(_, sub(A, B, C)) --> instruction_format_F0(0, A, B, sub, C). +asm(_, sub_carry(A, B, C)) --> instruction_format_F0(1, A, B, sub, C). + +asm(_, add_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, add, Imm). +asm(_, add_imm(A, B, Imm)) --> {pos_int15(Imm)}, !, instruction_format_F1(0, 0, A, B, add, Imm). +asm(_, add_imm_carry(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(1, 1, A, B, add, Imm). +asm(_, add_imm_carry(A, B, Imm)) --> {pos_int15(Imm)}, !, instruction_format_F1(1, 0, A, B, add, Imm). +asm(_, sub_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, sub, Imm). +asm(_, sub_imm(A, B, Imm)) --> {pos_int15(Imm)}, !, instruction_format_F1(0, 0, A, B, sub, Imm). +asm(_, sub_imm_carry(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(1, 1, A, B, sub, Imm). +asm(_, sub_imm_carry(A, B, Imm)) --> {pos_int15(Imm)}, !, instruction_format_F1(1, 0, A, B, sub, Imm). + +asm(_, mul(A, B, C)) --> instruction_format_F0(0, A, B, mul, C). +asm(_, mul_unsigned(A, B, C)) --> instruction_format_F0(1, A, B, mul, C). +asm(_, mul_imm(A, B, Imm, U)) --> {neg_int15(Imm)}, !, instruction_format_F1(U, 1, A, B, mul, Imm). +asm(_, mul_imm(A, B, Imm, U)) --> {pos_int15(Imm)}, !, instruction_format_F1(U, 0, A, B, mul, Imm). + +asm(_, and(A, B, C)) --> instruction_format_F0(0, A, B, and, C). +asm(_, ann(A, B, C)) --> instruction_format_F0(0, A, B, ann, C). +asm(_, asr(A, B, C)) --> instruction_format_F0(0, A, B, asr, C). +asm(_, div(A, B, C)) --> instruction_format_F0(0, A, B, div, C). +asm(_, ior(A, B, C)) --> instruction_format_F0(0, A, B, ior, C). +asm(_, lsl(A, B, C)) --> instruction_format_F0(0, A, B, lsl, C). +asm(_, ror(A, B, C)) --> instruction_format_F0(0, A, B, ror, C). +asm(_, xor(A, B, C)) --> instruction_format_F0(0, A, B, xor, C). + +asm(_, and_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, and, Imm). +asm(_, and_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, and, Imm). +asm(_, ann_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, ann, Imm). +asm(_, ann_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, ann, Imm). +asm(_, asr_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, asr, Imm). +asm(_, asr_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, asr, Imm). +asm(_, div_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, div, Imm). +asm(_, div_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, div, Imm). +asm(_, ior_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, ior, Imm). +asm(_, ior_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, ior, Imm). +asm(_, lsl_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, lsl, Imm). +asm(_, lsl_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, lsl, Imm). +asm(_, ror_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, ror, Imm). +asm(_, ror_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, ror, Imm). +asm(_, xor_imm(A, B, Imm)) --> {neg_int15(Imm)}, !, instruction_format_F1(0, 1, A, B, xor, Imm). +asm(_, xor_imm(A, B, Imm)) --> {pos_int16(Imm)}, !, instruction_format_F1(0, 0, A, B, xor, Imm). + +asm(_, cc(C)) --> instruction_format_F3a(0, cc, C). +asm(N, cc_offset(Label)) --> instruction_format_F3b(0, cc, Label, N). +asm(_, cc_link(C)) --> instruction_format_F3a(1, cc, C). +asm(N, cc_link_offset(Label)) --> instruction_format_F3b(1, cc, Label, N). +asm(_, cs(C)) --> instruction_format_F3a(0, cs, C). +asm(N, cs_offset(Label)) --> instruction_format_F3b(0, cs, Label, N). +asm(_, cs_link(C)) --> instruction_format_F3a(1, cs, C). +asm(N, cs_link_offset(Label)) --> instruction_format_F3b(1, cs, Label, N). +asm(_, do(C)) --> instruction_format_F3a(0, do, C). +asm(N, do_offset(Label)) --> instruction_format_F3b(0, do, Label, N). +asm(_, do_link(C)) --> instruction_format_F3a(1, do, C). +asm(N, do_link_offset(Label)) --> instruction_format_F3b(1, do, Label, N). +asm(_, eq(C)) --> instruction_format_F3a(0, eq, C). +asm(N, eq_offset(Label)) --> instruction_format_F3b(0, eq, Label, N). +asm(_, eq_link(C)) --> instruction_format_F3a(1, eq, C). +asm(N, eq_link_offset(Label)) --> instruction_format_F3b(1, eq, Label, N). +asm(_, ge(C)) --> instruction_format_F3a(0, ge, C). +asm(N, ge_offset(Label)) --> instruction_format_F3b(0, ge, Label, N). +asm(_, ge_link(C)) --> instruction_format_F3a(1, ge, C). +asm(N, ge_link_offset(Label)) --> instruction_format_F3b(1, ge, Label, N). +asm(_, gt(C)) --> instruction_format_F3a(0, gt, C). +asm(N, gt_offset(Label)) --> instruction_format_F3b(0, gt, Label, N). +asm(_, gt_link(C)) --> instruction_format_F3a(1, gt, C). +asm(N, gt_link_offset(Label)) --> instruction_format_F3b(1, gt, Label, N). +asm(_, hi(C)) --> instruction_format_F3a(0, hi, C). +asm(N, hi_offset(Label)) --> instruction_format_F3b(0, hi, Label, N). +asm(_, hi_link(C)) --> instruction_format_F3a(1, hi, C). +asm(N, hi_link_offset(Label)) --> instruction_format_F3b(1, hi, Label, N). +asm(_, le(C)) --> instruction_format_F3a(0, le, C). +asm(N, le_offset(Label)) --> instruction_format_F3b(0, le, Label, N). +asm(_, le_link(C)) --> instruction_format_F3a(1, le, C). +asm(N, le_link_offset(Label)) --> instruction_format_F3b(1, le, Label, N). +asm(_, ls(C)) --> instruction_format_F3a(0, ls, C). +asm(N, ls_offset(Label)) --> instruction_format_F3b(0, ls, Label, N). +asm(_, ls_link(C)) --> instruction_format_F3a(1, ls, C). +asm(N, ls_link_offset(Label)) --> instruction_format_F3b(1, ls, Label, N).