From 6f6dfb0ada61416ecc3782ae271638ec01b784b3 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 7 Jun 2020 04:19:07 +0200 Subject: [PATCH] skeleton of expression evaluator is now ready --- Makefile | 1 + c64/basic/engine/ad9e.frmevl.s | 135 +++++++++++++++++++++++++++++-- c64/basic/engine/injest_spaces.s | 4 +- c64/basic/operators/oper_plus.s | 42 ++++++++++ 4 files changed, 172 insertions(+), 10 deletions(-) create mode 100644 c64/basic/operators/oper_plus.s diff --git a/Makefile b/Makefile index 7730af5e..3aa682b4 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \ c64/basic/math \ c64/basic/math_consts \ c64/basic/math_mov \ + c64/basic/operators \ c64/basic/print \ c64/basic/rom_revision \ c64/basic/wedge diff --git a/c64/basic/engine/ad9e.frmevl.s b/c64/basic/engine/ad9e.frmevl.s index da1f3f16..e5d27ddf 100644 --- a/c64/basic/engine/ad9e.frmevl.s +++ b/c64/basic/engine/ad9e.frmevl.s @@ -14,24 +14,62 @@ // - INTFLG (XXX float/integer, probably) // - for float: FAC1 // - for string: __FAC1 + 0 = length, __FAC1 + 1 = pointer to string +// +// Idea: +// - use a stack to reorder operations, so that they can be executed +// in a correct order +// // XXX finish the implementation FRMEVL: + // Put the sentinel to the stack + + lda #$00 + pha + + // FALLTROUGH + +FRMEVL_loop: + // Check if end of statement jsr end_of_statement_check bcs_16 do_SYNTAX_error - // Search for opening quote + // There are 4 basic possibilities: a string, a float, an opening bracket, or a token jsr fetch_character - cmp #$22 - bne FRMEVL_fetch_float + cmp #$22 // check for opening quote + beq FRMEVL_fetch_string + cmp #$28 // check for opening bracket + beq_16 do_NOT_IMPLEMENTED_error // XXX + cmp #$7F // check for a token + bcc FRMEVL_fetch_float - // FALLTROUGH + // Search for a value or unary operator, starting from the most probable + // XXX check for BASIC functions here, too + + cmp #$AB // check for unary minus + beq_16 do_NOT_IMPLEMENTED_error // XXX + cmp #$A8 // check for NOT + beq_16 do_NOT_IMPLEMENTED_error // XXX + cmp #$FF // check for PI + beq_16 do_NOT_IMPLEMENTED_error // XXX + cmp #$AA // check for unary plus (ignore this one) + beq FRMEVL_loop + + // Nothing recognized + + jmp do_SYNTAX_error + +FRMEVL_fetch_float: + + // XXX implement this + + jmp do_SYNTAX_error FRMEVL_fetch_string: @@ -54,19 +92,100 @@ FRMEVL_fetch_string: jsr fetch_character cmp #$22 - beq FRMEVL_done + beq FRMEVL_got_value inc __FAC1 + 0 bne !- jmp do_STRING_TOO_LONG_error -FRMEVL_fetch_float: +FRMEVL_got_value: - // XXX implement this + jsr end_of_statement_check + bcs FRMEVL_calculate - jmp do_SYNTAX_error + // FALLTROUGH + +FRMEVL_fetch_operator: + + // We have a value, but this is not the end of expression. We expect + // a two argument operator here. First make sure we have enough space + // on a stack - we will surely need it + + tsx + cpx #$40 // XXX is this a safe threshold? + bcc_16 do_FORMULA_TOO_COMPLEX_error + + // Now look for an operator + // XXX for now only plus operator is implemented + + jsr fetch_character + cmp #$AA // check for a plus operator + beq_16 FRMEVL_push_value_operator + + // Something unknown - consider this the end of expression + + // FALTROUGH + +FRMEVL_calculate: // this is the exit point for the operators + + // Now, we have to calculate all the operations; at this point we + // should have a value in FAC1 and (possibly) operator on the stack + + pla + beq FRMEVL_done // branch if sentinel + + // Priority can be ignored now - just jump to the operator + + // FALLTROUGH FRMEVL_done: rts + +FRMEVL_push_value_operator: + + // First push the value in FAC1/ARG1 + + ldx VALTYP + bmi FRMEVL_push_string + + // Push float + + // XXX implement this + +FRMEVL_push_string: + + // Push string - address, length, type + + lda __FAC1+1 + pha + lda __FAC1+2 + pha + + lda __FAC1+0 + pha + + txa + pha + +FRMEVL_push_operator_address: + + // Push the operator address to stack, in a form + // suitable for RTS + + // XXX add support for other operators + + lda #>(oper_plus - 1) + pha + lda #<(oper_plus - 1) + pha + + // Push operator priority + + lda #$01 // XXX add support for other operators + pha + + // Continue + + jmp FRMEVL_loop diff --git a/c64/basic/engine/injest_spaces.s b/c64/basic/engine/injest_spaces.s index 506112c6..fb018def 100644 --- a/c64/basic/engine/injest_spaces.s +++ b/c64/basic/engine/injest_spaces.s @@ -3,10 +3,10 @@ // #LAYOUT# * * #IGNORE // -// Injests all spaces. +// Injests all spaces // -// XXX get rid of this when proper number parsing is completed +// XXX get rid of this when proper number parsing is implemented injest_spaces: diff --git a/c64/basic/operators/oper_plus.s b/c64/basic/operators/oper_plus.s new file mode 100644 index 00000000..d330a88a --- /dev/null +++ b/c64/basic/operators/oper_plus.s @@ -0,0 +1,42 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +oper_plus: + + // This operator can be used either with two strings, or with two floats + // First check whether arguments match and then choose the variant + + pla + cmp VALTYP + bne_16 do_TYPE_MISMATCH_error + + lda VALTYP + bmi oper_plus_strings + + // FALLTROUGH + +oper_plus_floats: + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error + +oper_plus_strings: + + // Pull string length + + pla + sta __FAC2+0 + + // Retrieve string address + + pla + sta __FAC2+2 + pla + sta __FAC2+1 + + // XXX merge strings here + + jmp FRMEVL_calculate