feat(v4.0.0): the text assembler takes &NAME and CONST+N
&NAME is the address of a word as a literal; CONST+N is a loader constant plus an offset as one literal, so that a capsule file can address the cells of its scratch area without adding at run time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
26a6a16537
commit
44ffd261bb
@@ -26,6 +26,10 @@
|
||||
* 123 -5 $FF a literal: `@p` and its value. Decimal, or hex after $.
|
||||
* It must fit a cell, as a signed or an unsigned number.
|
||||
* CONST a constant given by v4_text_constant: a literal.
|
||||
* CONST+N the constant plus the number N: one literal. (Only when
|
||||
* the whole token is not itself a name.)
|
||||
* &NAME the address of the word NAME, which must already be
|
||||
* defined: a literal.
|
||||
* ; + dup a! ... an opcode. `@p` cannot be written; write the number.
|
||||
* jump X call X if X -if X next X
|
||||
* a branch to X: a label of this word if it has one of
|
||||
|
||||
+25
-1
@@ -300,7 +300,7 @@ static void end_word(v4_text *t)
|
||||
static void define(v4_text *t, const char *name, unsigned char kind, v4_cell value)
|
||||
{
|
||||
v4_cell v; int big;
|
||||
if (opcode_of(name) >= 0 || is_reserved(name) || is_label_def(name) || number_of(name, &v, &big)) {
|
||||
if (opcode_of(name) >= 0 || is_reserved(name) || is_label_def(name) || number_of(name, &v, &big) || name[0] == '&') {
|
||||
fail(t, "cannot be used as a name", name);
|
||||
return;
|
||||
}
|
||||
@@ -427,6 +427,14 @@ static void one_token(v4_text *t, reader *r, const char *tok)
|
||||
return;
|
||||
}
|
||||
|
||||
if (tok[0] == '&' && tok[1] != 0) { /* the address of a word, as a literal */
|
||||
s = find(t, tok + 1);
|
||||
if (!s || s->kind != KIND_WORD) { fail(t, "& needs a word that is already defined", tok + 1); return; }
|
||||
v4_asm_lit(as, s->value);
|
||||
check_asm(t, tok);
|
||||
return;
|
||||
}
|
||||
|
||||
s = find(t, tok);
|
||||
if (s && s->kind == KIND_MACRO) {
|
||||
if (r->depth == V4_TEXT_MAX_DEPTH + 1u) { fail(t, "macros nested too deep", tok); return; }
|
||||
@@ -444,6 +452,22 @@ static void one_token(v4_text *t, reader *r, const char *tok)
|
||||
check_asm(t, tok);
|
||||
return;
|
||||
}
|
||||
if (!s) { /* CONST+N: a constant and an offset, one literal */
|
||||
const char *plus = strrchr(tok, '+');
|
||||
if (plus && plus != tok && plus[1] != 0) {
|
||||
char left[V4_TEXT_MAX_TOKEN + 1u];
|
||||
const v4_text_symbol *c;
|
||||
size_t len = (size_t)(plus - tok);
|
||||
memcpy(left, tok, len);
|
||||
left[len] = 0;
|
||||
c = find(t, left);
|
||||
if (c && c->kind == KIND_CONST && number_of(plus + 1, &v, &big) && !big) {
|
||||
v4_asm_lit(as, (v4_cell)((v4_ucell)c->value + (v4_ucell)v));
|
||||
check_asm(t, tok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
branch(t, V4_OP_CALL, tok, 0); /* a word, defined already or later */
|
||||
}
|
||||
|
||||
|
||||
@@ -409,6 +409,21 @@ int main(void)
|
||||
CHECK(ok(": 2DUP over over ; : 1+ 1 + ; : T ( a b -- 2a+2b+1 ) 2DUP + + + 1+ ;") && result("T", 2, 2, 3) == 11,
|
||||
"names that begin with digits");
|
||||
|
||||
/* CONST+N: a constant and an offset as one literal */
|
||||
CHECK(ok(": T VAR+3 ;") && result("T", 0, 0, 0) == VARS + 3, "CONST+N is the constant plus N");
|
||||
CHECK(ok(": T VAR+0 VAR+10 + ;") && result("T", 0, 0, 0) == 2 * VARS + 10, "any N");
|
||||
CHECK(nb.mem[ORIGIN + 1] == VARS && nb.mem[ORIGIN + 2] == VARS + 10, "and it is a single literal");
|
||||
CHECK(ok(": VAR+1 77 ; : T VAR+1 ;") && result("T", 0, 0, 0) == 77, "a word of that very name comes first");
|
||||
CHECK(refused(": T VAR+ ;", "never defined", 1) && refused(": T VAR+x ;", "never defined", 1) && refused(": T NOPE+1 ;", "never defined", 1),
|
||||
"what is not a constant and a number is just an unknown name");
|
||||
|
||||
/* &NAME: a word's address as a literal */
|
||||
CHECK(ok(": A 5 ; : T &A ;") && result("T", 0, 0, 0) == v4_text_word(&tx, "A"), "&NAME is the word's address");
|
||||
CHECK(ok(": A 5 ; : T &A push ;") && result("T", 0, 0, 0) == 5, "which can be executed");
|
||||
CHECK(refused(": T &A ; : A 5 ;", "already defined", 1), "the word must be defined first");
|
||||
CHECK(refused(": T &VAR ;", "already defined", 1), "and be a word");
|
||||
CHECK(refused(": &X 1 ;", "cannot be used as a name", 1), "a name cannot begin with &");
|
||||
|
||||
/* headers: a dictionary entry in front of a word (capsule/dict.v4) */
|
||||
CHECK(ok("header DUP : (DUP) dup + ;"), "a header assembles: %s", v4_text_error(&tx));
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user