Allow vectors to be decorated with inputs/outputs/trashes; test.
Chris Pressey
9 years ago
32 | 32 | |
33 | 33 | For 0.6: |
34 | 34 | |
35 | * `interrupt` routines. | |
36 | * `goto` (tail call). | |
37 | * `vector` type... with declared `inputs` `outputs` `trashes`? | |
38 | * `copy` instruction... that can copy a constant to a user-def mem loc. | |
35 | * declared `inputs` `outputs` `trashes` on the `vector` type. | |
36 | * `goto` (tail call) a routine or a vector. | |
39 | 37 | * A more involved demo for the C64 — one that sets up an interrupt. |
40 | 38 | |
41 | 39 | For 0.7: |
47 | 45 | |
48 | 46 | At some point... |
49 | 47 | |
48 | * `interrupt` routines. | |
50 | 49 | * add line number (or at least routine name) to error messages. |
51 | 50 | * 6502-mnemonic aliases (`sec`, `clc`) |
52 | 51 | * other handy aliases (`eq` for `z`, etc.) |
52 | * have `copy` instruction able to copy a constant to a user-def mem loc, etc. | |
53 | 53 | * add absolute addressing in shl/shr, absolute-indexed for add, sub, etc. |
54 | 54 | * check and disallow recursion. |
82 | 82 | |
83 | 83 | byte table screen @ 1024 |
84 | 84 | |
85 | A user-defined vector memory location is decorated with READS and WRITES lists | |
86 | like a routine (see below), and it may only hold addresses of routines which | |
87 | are compatible. (Meaning, the routine's inputs (resp. outputs, trashes) | |
88 | must be a subset of the vector's inputs (resp. outputs, trashes.)) | |
89 | ||
90 | vector actor_logic | |
91 | inputs a, score | |
92 | outputs x | |
93 | trashes y | |
94 | @ $c000 | |
95 | ||
85 | 96 | Routines |
86 | 97 | -------- |
87 | 98 | |
349 | 360 | ------- |
350 | 361 | |
351 | 362 | Program ::= {Defn} {Routine}. |
352 | Defn ::= "byte" ["table"] NewIdent ["@" WordConst]. | |
353 | Routine ::= "routine" NewIdent | |
354 | ["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs] | |
355 | (Block | "@" WordConst). | |
363 | Defn ::= Type NewIdent [Constraints] ["@" WordConst]. | |
364 | Type ::= "byte" ["table"] | "vector" | |
365 | Constrnt::= ["inputs" LocExprs] ["outputs" LocExprs] ["trashes" LocExprs]. | |
366 | Routine ::= "routine" NewIdent Constraints (Block | "@" WordConst). | |
356 | 367 | LocExprs::= LocExpr {"," LocExpr}. |
357 | 368 | LocExpr ::= Register | Flag | LitByte | DefnIdent. |
358 | 369 | Register::= "a" | "x" | "y". |
131 | 131 | self.scanner.check_type('identifier') |
132 | 132 | name = self.scanner.token |
133 | 133 | self.scanner.scan() |
134 | ||
135 | (inputs, outputs, trashes) = self.constraints() | |
136 | if type != TYPE_VECTOR and (inputs or outputs or trashes): | |
137 | raise SyntaxError("Cannot apply constraints to non-vector type") | |
138 | ||
134 | 139 | addr = None |
135 | 140 | if self.scanner.consume('@'): |
136 | 141 | self.scanner.check_type('integer literal') |
137 | 142 | addr = int(self.scanner.token) |
138 | 143 | self.scanner.scan() |
139 | return Defn(name=name, type=type, addr=addr) | |
140 | ||
141 | def routine(self): | |
142 | self.scanner.expect('routine') | |
143 | name = self.scanner.token | |
144 | self.scanner.scan() | |
144 | return Defn(name=name, type=type, addr=addr, | |
145 | inputs=inputs, outputs=outputs, trashes=trashes) | |
146 | ||
147 | def constraints(self): | |
145 | 148 | inputs = [] |
146 | 149 | outputs = [] |
147 | 150 | trashes = [] |
151 | 154 | outputs = self.locexprs() |
152 | 155 | if self.scanner.consume('trashes'): |
153 | 156 | trashes = self.locexprs() |
157 | return (inputs, outputs, trashes) | |
158 | ||
159 | def routine(self): | |
160 | self.scanner.expect('routine') | |
161 | name = self.scanner.token | |
162 | self.scanner.scan() | |
163 | (inputs, outputs, trashes) = self.constraints() | |
154 | 164 | if self.scanner.consume('@'): |
155 | 165 | self.scanner.check_type('integer literal') |
156 | 166 | block = None |
988 | 988 | | } |
989 | 989 | ? UninitializedAccessError: x |
990 | 990 | |
991 | Can't `st` to a memory location that doesn't appear in (outputs ∪ trashes). | |
991 | Can't `copy` to a memory location that doesn't appear in (outputs ∪ trashes). | |
992 | 992 | |
993 | 993 | | byte lives |
994 | 994 | | routine main |
1035 | 1035 | | copy 0, lives |
1036 | 1036 | | } |
1037 | 1037 | ? UninitializedOutputError: a |
1038 | ||
1039 | Unless of course you subsequently initialize them. | |
1040 | ||
1041 | | byte lives | |
1042 | | routine main | |
1043 | | outputs lives, a, z, n | |
1044 | | { | |
1045 | | copy 0, lives | |
1046 | | ld a, 0 | |
1047 | | } | |
1048 | = ok | |
1049 | ||
1050 | You can copy the address of a routine into a vector, if that vector is declared appropriately. | |
1051 | ||
1052 | | vector vec | |
1053 | | inputs x | |
1054 | | outputs x | |
1055 | | trashes z, n | |
1056 | | | |
1057 | | routine foo | |
1058 | | inputs x | |
1059 | | outputs x | |
1060 | | trashes z, n | |
1061 | | { | |
1062 | | inc x | |
1063 | | } | |
1064 | | | |
1065 | | routine main | |
1066 | | inputs foo | |
1067 | | outputs vec | |
1068 | | trashes a, z, n | |
1069 | | { | |
1070 | | copy foo, vec | |
1071 | | } | |
1072 | = ok | |
1073 | ||
1074 | But not if the vector is declared inappropriately. | |
1075 | ||
1076 | | vector vec | |
1077 | | inputs y | |
1078 | | outputs y | |
1079 | | trashes z, n | |
1080 | | | |
1081 | | routine foo | |
1082 | | inputs x | |
1083 | | outputs x | |
1084 | | trashes z, n | |
1085 | | { | |
1086 | | inc x | |
1087 | | } | |
1088 | | | |
1089 | | routine main | |
1090 | | inputs foo | |
1091 | | outputs vec | |
1092 | | trashes a, z, n | |
1093 | | { | |
1094 | | copy foo, vec | |
1095 | | } | |
1096 | ? IllegalWriteError |
217 | 217 | Declaring a vector. |
218 | 218 | |
219 | 219 | | vector cinv |
220 | | inputs a | |
221 | | outputs x | |
222 | | trashes a, x, z, n | |
223 | | @ 788 | |
220 | 224 | | |
221 | 225 | | routine foo { |
222 | 226 | | ld a, 0 |
227 | 231 | | } |
228 | 232 | | } |
229 | 233 | = ok |
234 | ||
235 | Only vectors can be decorated with constraints like that. | |
236 | ||
237 | | byte cinv | |
238 | | inputs a | |
239 | | outputs x | |
240 | | trashes a, x, z, n | |
241 | | @ 788 | |
242 | | | |
243 | | routine main { | |
244 | | } | |
245 | ? SyntaxError |