Skip to content

Commit bba303b

Browse files
unified expression: printable syntax fixes for negation/unary ops
1 parent 2dda80c commit bba303b

8 files changed

Lines changed: 446 additions & 328 deletions

File tree

include/basic/process.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,13 @@ int64_t basic_get_program_cur_mem(struct basic_ctx* ctx);
123123
* @return The state of the process (e.g., "running", "suspended", "waiting").
124124
*/
125125
char* basic_getprocstate(struct basic_ctx* ctx);
126+
127+
void chain_statement(struct basic_ctx* ctx);
128+
129+
void rem_statement(struct basic_ctx* ctx);
130+
131+
void eval_statement(struct basic_ctx* ctx);
132+
133+
void goto_statement(struct basic_ctx* ctx);
134+
135+
void yield_statement(struct basic_ctx* ctx);

include/basic/unified_expression.h

Lines changed: 127 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
#pragma once
2-
#include <kernel.h>
3-
41
/**
52
* @file unified_expression.h
63
* @brief Typed expression and conditional entry points for the unified parser.
@@ -11,41 +8,91 @@
118
* integer, real, and string expressions.
129
*
1310
* ### Tokeniser interaction
14-
* - **Parentheses**: content inside `(` `)` is parsed as a relation-aware
15-
* expression so forms such as `(in<128)` are valid in IF/WHILE.
16-
* - **String literals**: obtained via `tokenizer_string(...)`. No subsequent
17-
* `accept(STRING)` is performed; the tokeniser already advances to lookahead.
11+
* - **Parentheses**: content inside `(` .. `)` is parsed as a relation-aware
12+
* expression, so forms such as `(in<128)` are valid in IF/WHILE.
13+
* - **String literals**: obtained via `tokenizer_string(...)` and then
14+
* `accept(STRING)`; the tokeniser produces the literal and we consume it.
1815
* - **Variables and built-ins**:
19-
* - Names ending with `$` → STRING.
20-
* - Names ending with `#` → REAL.
21-
* - Unsuffixed names → INT, *except* for a temporary whitelist of known
22-
* real-returning built-ins (implemented in the `.c` file):
23-
* `ACS, ASN, ATAN, ATAN2, CEIL, COS, DEG, EXP, FMOD, GETVARR, LOG, POW,
24-
* RAD, REALVAL, ROUND, SIN, SQRT, TAN`.
25-
*
26-
* ### Operators
16+
* - Names ending with `$` - STRING.
17+
* - Names ending with `#` - REAL.
18+
* - Unsuffixed names default to INT *unless* the core marks them as real
19+
* built-ins (queried via the interpreter’s registry, e.g.
20+
* `is_builtin_double_fn(name)`).
21+
*
22+
* ### Operators and precedence
23+
* - **Unary**: leading `+` / `-` bind **tighter** than `* / MOD`.
24+
* Applies to numeric values only (e.g. `A--3`, `-(2+3)`, `-SIN(ANGLE#)`).
2725
* - **Arithmetic**: `+ - * / MOD`
28-
* - Numeric arithmetic; `+` concatenates when both operands are strings.
29-
* - Mixed string/numeric on `+` or `-` is an error. `MOD` requires integers.
30-
* - Division by zero emits a kernel-style error. INT+REAL promotes to REAL.
31-
* - **Bitwise**: `AND OR EOR`
32-
* - Numeric only; REAL operands are cast to `int64_t`; strings are an error.
26+
* - Numeric arithmetic; `+` concatenates when **both** operands are strings.
27+
* - Mixing string and numeric with `+`/`-` is an error. `MOD` requires INTs.
28+
* - INT↔REAL promotes to REAL; division by zero reports a runtime error.
3329
* - **Relational**: `< > = <= >= <>`
3430
* - Numeric comparisons promote INT↔REAL. String comparisons use `strcmp`.
3531
* - Result is INT 0/1.
36-
* - **Boolean precedence (conditionals)**: `NOT` > `AND` > `OR`, left-associative.
32+
* - **Boolean (conditionals)**: `NOT` > `AND` > `OR`, all left-associative.
3733
*
3834
* ### Consumption and stop conditions
39-
* - `up_conditional()` stops before `THEN` / `NEWLINE` / `EOF` / `')'`. `THEN`
40-
* is not consumed; statement parsers should continue to `accept(THEN, ctx)`.
35+
* - `up_conditional()` stops before `THEN` / `NEWLINE` / `EOF` / `')'`.
36+
* The caller should `accept(THEN, ctx)` if required.
37+
* - `up_eval_value()` parses one value expression and **leaves** list
38+
* separators (`,` / `;`), `THEN`, `NEWLINE`, and `EOF` untouched for the
39+
* enclosing statement (e.g. `PRINT`, `INPUT`) to handle.
4140
*
4241
* ### String lifetime
43-
* - String results are duplicated with the GC (`gc_strdup`) to match existing
44-
* `str_expr` behaviour.
42+
* - String results returned by expression evaluation are duplicated via the
43+
* GC (`gc_strdup`) to match historic `str_expr` behaviour.
44+
*/
45+
46+
#pragma once
47+
#include <kernel.h>
48+
49+
/**
50+
* @enum up_kind
51+
* @brief Discriminant for a typed value produced by the unified evaluator.
4552
*
46-
* @note The temporary real-builtin whitelist can be replaced by a descriptor
47-
* table (name → return type) without API changes.
53+
* Enumerates the runtime kind carried by an ::up_value.
4854
*/
55+
typedef enum {
56+
/** 64-bit signed integer value. */
57+
UP_INT,
58+
/** IEEE-754 double-precision real value. */
59+
UP_REAL,
60+
/** NUL-terminated string pointer. */
61+
UP_STR
62+
} up_kind;
63+
64+
/**
65+
* @struct up_value
66+
* @brief Discriminated union carrying a typed expression result.
67+
*
68+
* Represents one value returned by the unified expression evaluator.
69+
* The active member of the union is indicated by ::up_value::kind.
70+
*
71+
* @var up_value::kind
72+
* Tag identifying the active member in ::up_value::v.
73+
*
74+
* @var up_value::v
75+
* Anonymous union holding the underlying value.
76+
*
77+
* @var up_value::v::i
78+
* 64-bit signed integer; valid when ::up_value::kind is ::UP_INT.
79+
*
80+
* @var up_value::v::r
81+
* Double-precision real; valid when ::up_value::kind is ::UP_REAL.
82+
*
83+
* @var up_value::v::s
84+
* Pointer to a NUL-terminated string; valid when ::up_value::kind is ::UP_STR.
85+
* Ownership/lifetime is external to this struct (typically GC-managed).
86+
*/
87+
typedef struct {
88+
up_kind kind;
89+
union {
90+
int64_t i;
91+
double r;
92+
const char *s;
93+
} v;
94+
} up_value;
95+
4996

5097
/**
5198
* @brief Evaluate a BASIC conditional (boolean) expression.
@@ -75,7 +122,7 @@ bool up_conditional(struct basic_ctx *ctx);
75122
int64_t up_relation_i(struct basic_ctx *ctx);
76123

77124
/* ------------------------------------------------------------------------- */
78-
/* Strict shims drop-in replacements for legacy int/real/string expr APIs. */
125+
/* Strict shims - drop-in replacements for legacy int/real/string expr APIs. */
79126
/* ------------------------------------------------------------------------- */
80127

81128
/**
@@ -110,3 +157,55 @@ void up_double_expr_strict(struct basic_ctx *ctx, double *out);
110157
* @return Non-NULL GC-managed string pointer.
111158
*/
112159
const char* up_str_expr_strict(struct basic_ctx *ctx);
160+
161+
/**
162+
* @brief Construct a typed value holding an integer.
163+
*
164+
* @param x Signed 64-bit integer to store.
165+
* @return up_value tagged as UP_INT with @p x in the integer field.
166+
*
167+
* @note No allocation is performed.
168+
*/
169+
up_value up_make_int(int64_t x);
170+
171+
/**
172+
* @brief Construct a typed value holding a real (double).
173+
*
174+
* @param x Double to store.
175+
* @return up_value tagged as UP_REAL with @p x in the real field.
176+
*
177+
* @note No allocation is performed.
178+
*/
179+
up_value up_make_real(double x);
180+
181+
/**
182+
* @brief Construct a typed value holding a string pointer.
183+
*
184+
* @param s Pointer to NUL-terminated string to store (may be NULL).
185+
* @return up_value tagged as UP_STR with @p s in the string field.
186+
*
187+
* @note The pointer is stored as-is; lifetime/ownership of @p s must be
188+
* managed by the caller (typically GC-allocated in this interpreter).
189+
* No copy is made here.
190+
*/
191+
up_value up_make_str(const char *s);
192+
193+
/**
194+
* @brief Evaluate a single value expression and return its typed result.
195+
*
196+
* Parses one expression using the unified evaluator and writes the result to
197+
* @p out without coercion (the kind will be UP_INT, UP_REAL, or UP_STR).
198+
*
199+
* @param ctx BASIC interpreter context; @c ctx->ptr must point at the start
200+
* of the expression to evaluate.
201+
* @param[out] out Receives the typed result of the evaluation.
202+
*
203+
* @post On return, @c ctx->ptr is positioned at the first token not consumed
204+
* by the expression. In particular, list separators (','/';'), THEN,
205+
* NEWLINE, and ENDOFINPUT are left untouched for the caller to handle.
206+
*
207+
* @note Errors encountered during evaluation are reported via the existing
208+
* error machinery (e.g. @c tokenizer_error_print) and reflected in
209+
* @c ctx->errored; this function does not throw or longjmp.
210+
*/
211+
void up_eval_value(struct basic_ctx *ctx, up_value *out);

include/scsi.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ typedef enum scsi_additional_sense_code_qualifier_t {
5454
SCSI_ASCQ_ANY = 0xFF, /* Wildcard */
5555
} scsi_additional_sense_code_qualifier_t;
5656

57-
/* INQUIRY(6) 6 bytes */
57+
/* INQUIRY(6) - 6 bytes */
5858
typedef struct __attribute__((packed)) scsi_cdb_inquiry6 {
5959
uint8_t opcode; /* 0x12 */
6060
uint8_t evpd; /* bit0 = EVPD */
@@ -64,7 +64,7 @@ typedef struct __attribute__((packed)) scsi_cdb_inquiry6 {
6464
uint8_t control; /* 0 */
6565
} scsi_cdb_inquiry6;
6666

67-
/* READ(12) 12 bytes; LBA and transfer length are big-endian */
67+
/* READ(12) - 12 bytes; LBA and transfer length are big-endian */
6868
typedef struct __attribute__((packed)) scsi_cdb_read12 {
6969
uint8_t opcode; /* 0xA8 */
7070
uint8_t flags; /* DPO/FUA/etc */
@@ -74,7 +74,7 @@ typedef struct __attribute__((packed)) scsi_cdb_read12 {
7474
uint8_t control; /* 0 */
7575
} scsi_cdb_read12;
7676

77-
/* TEST UNIT READY (6) opcode 0x00 */
77+
/* TEST UNIT READY (6) - opcode 0x00 */
7878
typedef struct __attribute__((packed)) scsi_cdb_test_unit_ready6 {
7979
uint8_t opcode; /* 0x00 */
8080
uint8_t rsv1;
@@ -84,7 +84,7 @@ typedef struct __attribute__((packed)) scsi_cdb_test_unit_ready6 {
8484
uint8_t control;
8585
} scsi_cdb_test_unit_ready6;
8686

87-
/* REQUEST SENSE (6) opcode 0x03 */
87+
/* REQUEST SENSE (6) - opcode 0x03 */
8888
typedef struct __attribute__((packed)) scsi_cdb_request_sense6 {
8989
uint8_t opcode; /* 0x03 */
9090
uint8_t desc; /* bit0 = DESC; usually 0 */
@@ -94,7 +94,7 @@ typedef struct __attribute__((packed)) scsi_cdb_request_sense6 {
9494
uint8_t control;
9595
} scsi_cdb_request_sense6;
9696

97-
/* START STOP UNIT (6) opcode 0x1B */
97+
/* START STOP UNIT (6) - opcode 0x1B */
9898
typedef struct __attribute__((packed)) scsi_cdb_start_stop_unit6 {
9999
uint8_t opcode; /* 0x1B */
100100
uint8_t immed; /* bit0 IMMED */
@@ -104,7 +104,7 @@ typedef struct __attribute__((packed)) scsi_cdb_start_stop_unit6 {
104104
uint8_t control;
105105
} scsi_cdb_start_stop_unit6;
106106

107-
/* PREVENT/ALLOW MEDIUM REMOVAL (6) opcode 0x1E */
107+
/* PREVENT/ALLOW MEDIUM REMOVAL (6) - opcode 0x1E */
108108
typedef struct __attribute__((packed)) scsi_cdb_prevent_allow6 {
109109
uint8_t opcode; /* 0x1E */
110110
uint8_t rsv1;
@@ -114,7 +114,7 @@ typedef struct __attribute__((packed)) scsi_cdb_prevent_allow6 {
114114
uint8_t control;
115115
} scsi_cdb_prevent_allow6;
116116

117-
/* SYNCHRONIZE CACHE (10) opcode 0x35 */
117+
/* SYNCHRONIZE CACHE (10) - opcode 0x35 */
118118
typedef struct __attribute__((packed)) scsi_cdb_synchronize_cache10 {
119119
uint8_t opcode; /* 0x35 */
120120
uint8_t flags; /* e.g. SYNC NV; usually 0 */
@@ -124,7 +124,7 @@ typedef struct __attribute__((packed)) scsi_cdb_synchronize_cache10 {
124124
uint8_t control;
125125
} scsi_cdb_synchronize_cache10;
126126

127-
/* MODE SENSE (10) opcode 0x5A */
127+
/* MODE SENSE (10) - opcode 0x5A */
128128
typedef struct __attribute__((packed)) scsi_cdb_mode_sense10 {
129129
uint8_t opcode; /* 0x5A */
130130
uint8_t dbd; /* bit3 DBD; often set to 1 */
@@ -136,7 +136,7 @@ typedef struct __attribute__((packed)) scsi_cdb_mode_sense10 {
136136
uint8_t control;
137137
} scsi_cdb_mode_sense10;
138138

139-
/* READ(16)/WRITE(16) opcodes 0x88 / 0x8A */
139+
/* READ(16)/WRITE(16) - opcodes 0x88 / 0x8A */
140140
typedef struct __attribute__((packed)) scsi_cdb_rw16 {
141141
uint8_t opcode; /* 0x88 READ(16) or 0x8A WRITE(16) */
142142
uint8_t flags; /* DPO/FUA/etc; 0 if unused */

0 commit comments

Comments
 (0)