if statement

This commit is contained in:
Irmen de Jong 2017-12-27 12:39:19 +01:00
parent 9e87001ddb
commit a3faf07c8c
6 changed files with 139 additions and 69 deletions

View File

@ -100,6 +100,16 @@ def parse_arguments(text: str, sourceref: SourceRef) -> List[Tuple[str, Primitiv
raise TypeError("ast.Expression expected")
def parse_expr_as_comparison(text: str, context: Optional[SymbolTable], ppcontext: Optional[SymbolTable], sourceref: SourceRef) -> None:
src = SourceLine(text, sourceref)
text = src.preprocess()
try:
node = ast.parse(text, sourceref.file, mode="eval")
except SyntaxError as x:
raise src.to_error(str(x))
print("AST NODE", node)
def parse_expr_as_int(text: str, context: Optional[SymbolTable], ppcontext: Optional[SymbolTable], sourceref: SourceRef, *,
minimum: int=0, maximum: int=0xffff) -> int:
result = parse_expr_as_primitive(text, context, ppcontext, sourceref, minimum=minimum, maximum=maximum)

View File

@ -944,25 +944,25 @@ class Parser:
raise self.PError(str(x)) from x
def parse_subroutine_def(self, line: str) -> None:
match = re.match(r"^sub\s+(?P<name>\w+)\s+"
match = re.fullmatch(r"sub\s+(?P<name>\w+)\s+"
r"\((?P<parameters>[\w\s:,]*)\)"
r"\s*->\s*"
r"\((?P<results>[\w\s?,]*)\)\s*"
r"(?P<decltype>\s+=\s+(?P<address>\S*)|{)\s*$", line)
r"(?P<decltype>\s+=\s+(?P<address>\S*)|{)\s*", line)
if not match:
raise self.PError("invalid sub declaration")
code_decl = match.group("decltype") == "{"
name, parameterlist, resultlist, address_str = \
match.group("name"), match.group("parameters"), match.group("results"), match.group("address")
parameters = [(match.group("name"), match.group("target"))
for match in re.finditer(r"(?:(?:(?P<name>[\w]+)\s*:\s*)?(?P<target>[\w]+))(?:,|$)", parameterlist)]
groups = match.groupdict()
code_decl = groups["decltype"] == "{"
name, parameterlist, resultlist, address_str = groups["name"], groups["parameters"], groups["results"], groups["address"]
parameters = [(m.group("name"), m.group("target"))
for m in re.finditer(r"(?:(?:(?P<name>[\w]+)\s*:\s*)?(?P<target>[\w]+))(?:,|$)", parameterlist)]
for _, regs in parameters:
if regs not in REGISTER_SYMBOLS:
raise self.PError("invalid register(s) in parameter or return values")
all_paramnames = [p[0] for p in parameters if p[0]]
if len(all_paramnames) != len(set(all_paramnames)):
raise self.PError("duplicates in parameter names")
results = [match.group("name") for match in re.finditer(r"\s*(?P<name>(?:\w+)\??)\s*(?:,|$)", resultlist)]
results = [m.group("name") for m in re.finditer(r"\s*(?P<name>(?:\w+)\??)\s*(?:,|$)", resultlist)]
subroutine_block = None
if code_decl:
address = None
@ -1040,31 +1040,29 @@ class Parser:
return varname, datatype, length, matrix_dimensions, valuetext
def parse_statement(self, line: str) -> ParseResult._AstNode:
match = re.match(r"(?P<outputs>.*\s*=)\s*(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*$", line)
match = re.fullmatch(r"goto\s+(?P<subname>[\S]+?)\s*(\((?P<arguments>.*)\))?\s*", line)
if match:
# subroutine call (not a goto) with output param assignment
preserve = not bool(match.group("fcall"))
subname = match.group("subname")
arguments = match.group("arguments")
outputs = match.group("outputs")
# goto
groups = match.groupdict()
subname = groups["subname"]
if '!' in subname:
raise self.PError("goto is always without register preservation, should not have exclamation mark")
arguments = groups["arguments"]
return self.parse_call_or_goto(subname, arguments, None, False, True)
match = re.fullmatch(r"(?P<outputs>[^\(]*\s*=)?\s*(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*", line)
if match:
# subroutine call (not a goto) with possible output param assignment
groups = match.groupdict()
preserve = not bool(groups["fcall"])
subname = groups["subname"]
arguments = groups["arguments"]
outputs = groups["outputs"] or ""
if outputs.strip() == "=":
raise self.PError("missing assignment target variables")
outputs = outputs.rstrip("=")
if arguments or match.group(4):
if arguments or match.group(4): # group 4 = (possibly empty) parenthesis
return self.parse_call_or_goto(subname, arguments, outputs, preserve, False)
# apparently it is not a call (no arguments), fall through
match = re.match(r"(?P<goto>goto\s+)?(?P<subname>[\S]+?)\s*(?P<fcall>[!]?)\s*(\((?P<arguments>.*)\))?\s*$", line)
if match:
# subroutine or goto call, without output param assignment
is_goto = bool(match.group("goto"))
preserve = not bool(match.group("fcall"))
subname = match.group("subname")
arguments = match.group("arguments")
if is_goto:
return self.parse_call_or_goto(subname, arguments, None, preserve, True)
elif arguments or match.group(4):
return self.parse_call_or_goto(subname, arguments, None, preserve, False)
# apparently it is not a call (no arguments), fall through
if line == "return" or line.startswith(("return ", "return\t")):
return self.parse_return(line)
elif line.endswith(("++", "--")):

View File

@ -92,7 +92,6 @@ output raw
memory .float FL_FR4 = $e2ea ; .25
; @todo verify clobbered registers?
; note: fac1/2 might get clobbered even if not mentioned in the function's name.
; note: for subtraction and division, the left operand is in fac2, the right operand in fac1.
@ -589,4 +588,48 @@ sub input_chars (buffer: AX) -> (A?, Y) {
}
}
sub memcopy_basic () -> (A?, X?, Y?) {
; ---- copy a memory block by using a BASIC ROM routine @todo fix code
; it calls a function from the basic interpreter, so:
; - BASIC ROM must be banked in
; - the source block must be readable (so no RAM hidden under BASIC, Kernal, or I/O)
; - the target block must be writable (so no RAM hidden under I/O)
; higher addresses are copied first, so:
; - moving data to higher addresses works even if areas overlap
; - moving data to lower addresses only works if areas do not overlap
asm {
lda #<src_start
ldx #>src_start
sta $5f
stx $60
lda #<src_end
ldx #>src_end
sta $5a
stx $5b
lda #<(target_start + src_end - src_start)
ldx #>(target_start + src_end - src_start)
sta $58
stx $59
jmp $a3bf
}
}
; macro version of the above memcopy_basic routine: @todo macro support?
; MACRO PARAMS src_start, src_end, target_start
; lda #<src_start
; ldx #>src_start
; sta $5f
; stx $60
; lda #<src_end
; ldx #>src_end
; sta $5a
; stx $5b
; lda #<(target_start + src_end - src_start)
; ldx #>(target_start + src_end - src_start)
; sta $58
; stx $59
; jsr $a3bf
}

View File

@ -314,15 +314,15 @@ TODOS
Required building blocks: additional forms of 'go' statement: including an if clause, comparison statement.
- a primitive conditional branch instruction (special case of 'go'): directly translates to a branch instruction:
if[_XX] go <label>
if[_XX] goto <label>
XX is one of: (cc, cs, vc, vs, eq, ne, pos, min,
lt==cc, lts==min, gt==eq+cs, gts==eq+pos, le==cc+eq, les==neg+eq, ge==cs, ges==pos)
and when left out, defaults to ne (not-zero, i.e. true)
NOTE: some combination branches such as cc+eq an be peephole optimized see http://www.6502.org/tutorials/compare_beyond.html#2.2
- conditional go with expression: where the if[_XX] is followed by a <expression>
- conditional goto with expression: where the if[_XX] is followed by a <expression>
in that case, evaluate the <expression> first (whatever it is) and then emit the primitive if[_XX] go
if[_XX] <expression> go <label>
if[_XX] <expression> goto <label>
eventually translates to:
<expression-code>
bXX <label>
@ -347,15 +347,15 @@ if[_XX] [<expression>] {
(no else:)
if[_!XX] [<expression>] go il65_if_999_end ; !XX being the conditional inverse of XX
if[_!XX] [<expression>] goto il65_if_999_end ; !XX being the conditional inverse of XX
.... (true part)
il65_if_999_end ; code continues after this
(with else):
if[_XX] [<expression>] go il65_if_999
if[_XX] [<expression>] goto il65_if_999
... (else part)
go il65_if_999_end
goto il65_if_999_end
il65_if_999 ... (true part)
il65_if_999_end ; code continues after this
@ -364,7 +364,7 @@ il65_if_999_end ; code continues after this
==> DESUGARING ==>
compare X, Y
if_XX go ....
if_XX goto ....
XX based on <COMPARISON>.
@ -381,13 +381,13 @@ while[_XX] <expression> {
==> DESUGARING ==>
go il65_while_999_check ; jump to the check
goto il65_while_999_check ; jump to the check
il65_while_999
... (code)
go il65_while_999 ;continue
go il65_while_999_end ;break
goto il65_while_999 ;continue
goto il65_while_999_end ;break
il65_while_999_check
if[_XX] <expression> go il65_while_999 ; loop condition
if[_XX] <expression> goto il65_while_999 ; loop condition
il65_while_999_end ; code continues after this
@ -403,9 +403,9 @@ repeat {
il65_repeat_999
... (code)
go il65_repeat_999 ;continue
go il65_repeat_999_end ;break
if[_!XX] <expression> go il65_repeat_999 ; loop condition via conditional inverse of XX
goto il65_repeat_999 ;continue
goto il65_repeat_999_end ;break
if[_!XX] <expression> goto il65_repeat_999 ; loop condition via conditional inverse of XX
il65_repeat_999_end ; code continues after this
@ -425,17 +425,17 @@ for <loopvar> = <from_expression> to <to_expression> [step <step_expression>] {
loopvar = <from_expression>
compare loopvar, <to_expression>
if_ge go il65_for_999_end ; loop condition
if_ge goto il65_for_999_end ; loop condition
step = <step_expression> ; (store only if step < -1 or step > 1)
il65_for_999
go il65_for_999_end ;break
go il65_for_999_loop ;continue
goto il65_for_999_end ;break
goto il65_for_999_loop ;continue
.... (code)
il65_for_999_loop
loopvar += step ; (if step > 1 or step < -1)
loopvar++ ; (if step == 1)
loopvar-- ; (if step == -1)
go il65_for_999 ; continue the loop
goto il65_for_999 ; continue the loop
il65_for_999_end ; code continues after this
@ -487,3 +487,13 @@ and SPRITES (24x21 monochrome or 12x21 multicolor = 63 bytes)
### More Datatypes
@todo 24 and 32 bits integers, unsigned and signed?
### Some support for simple arithmetic
A *= Y
A = X * Y
A /= Y
A = Y / Y
@todo multiplication routines (8*8 -> 16, 8*16 -> 16, 16*16->16 (or 32?))
@todo division routines

View File

@ -45,10 +45,10 @@ start
sub printflt (float: AY) -> (A?, X?, Y?) {
c64.MOVFM!(AY)
goto c64.FPRINTLN!()
goto c64.FPRINTLN
; c64.FOUT!()
; c64util.print_string!(AY)
;goto c64.CHROUT!('\n')
;goto c64.CHROUT('\n')
}

View File

@ -18,6 +18,15 @@ start
c64util.print_string(name)
c64.CHROUT('\n')
;if_cc goto label
;if_cc label
;if_cc dsdaf + 33 < 22 label
;if_cc dsdaf + 33 < 22 goto label!
goto label
goto label()
label
SI = 1
c64.CINV = XY
SI = 0