mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
if statement
This commit is contained in:
parent
9e87001ddb
commit
a3faf07c8c
@ -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)
|
||||
|
@ -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(("++", "--")):
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
46
reference.md
46
reference.md
@ -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
|
||||
|
@ -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')
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user