forked from swissmicros/SDKdemo
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The tag type is used to add a label to any arbitrary object. It is parsed as `:Label:object`, and renders the same, except on the stack where it renders as `Label:object`. Note that the HP48 renders a label with an extra space. The space is apparently gone on the HP50. Fixes: #21 Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
- Loading branch information
Showing
16 changed files
with
411 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,26 @@ | ||
# Tag objects | ||
# Tagged objects | ||
|
||
## MKTAG | ||
Apply a tag to an object | ||
Tagged objects are a way to indicate what a value represents, using a *tag* | ||
between colons and preceding the object. For example, `:X:3` is a tagged | ||
integer, where the tag is `X` and the object is `3`. | ||
|
||
When displayed on the stack, tags are shown without the leading colon for | ||
readability. For example, the object above shows as `X:3` on the stack. | ||
|
||
## DTAG | ||
Remove a tag from an object | ||
## →Tag (ToTag) | ||
|
||
Apply a tag to an object. The tag is in level 1 as text or name. The object to | ||
be tagged is in level 2. For example, `"Hello" 1 →Tag` results in `:Hello:1`. | ||
Like on the HP calculators, it is possible to next tags. | ||
|
||
## Tag→ (FromTag) | ||
|
||
Expand a tagged object in level 1 into its object and tag. The object will be in | ||
level 2, the tag will be in level 1 as a text object. | ||
|
||
For example, `:Hello:1 Tag→` results in `"Hello"` in level 1 and `1` in level 2. | ||
|
||
## DeleteTag (DTAG) | ||
|
||
Remove a tag from an object. For example, `:Hello:1 DeleteTag` results in `1`. | ||
If there is no tag, the object is returned as is. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
// **************************************************************************** | ||
// tag.cc DB48X project | ||
// **************************************************************************** | ||
// | ||
// File Description: | ||
// | ||
// Tag type | ||
// | ||
// The tag type is used to tag objects | ||
// It otherwise evaluates and behaves like the tagged object | ||
// | ||
// | ||
// | ||
// | ||
// | ||
// **************************************************************************** | ||
// (C) 2023 Christophe de Dinechin <christophe@dinechin.org> | ||
// This software is licensed under the terms outlined in LICENSE.txt | ||
// **************************************************************************** | ||
// This file is part of DB48X. | ||
// | ||
// DB48X is free software: you can redistribute it and/or modify | ||
// it under the terms outlined in the LICENSE.txt file | ||
// | ||
// DB48X is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
// **************************************************************************** | ||
|
||
#include "tag.h" | ||
#include "parser.h" | ||
#include "renderer.h" | ||
|
||
|
||
SIZE_BODY(tag) | ||
// ---------------------------------------------------------------------------- | ||
// Compute the size of a tag object | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
byte_p p = o->payload(); | ||
size_t sz = leb128<size_t>(p); | ||
p += sz; | ||
sz = object_p(p)->size(); | ||
p += sz; | ||
return ptrdiff(p, o); | ||
} | ||
|
||
|
||
PARSE_BODY(tag) | ||
// ---------------------------------------------------------------------------- | ||
// Try to parse this as a tag, i.e. :LABEL:Object | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
utf8 source = p.source; | ||
utf8 s = source; | ||
if (*s++ != ':') | ||
return SKIP; | ||
|
||
utf8 end = source + p.length; | ||
while (s < end && *s != ':') | ||
s++; | ||
|
||
if (*s != ':') | ||
{ | ||
rt.unterminated_error().source(p.source); | ||
return ERROR; | ||
} | ||
s++; | ||
|
||
size_t parsed = s - source; | ||
size_t llen = parsed - 2; | ||
gcutf8 lbl = source + 1; | ||
|
||
size_t remaining = p.length - parsed; | ||
object_g obj = object::parse(s, remaining); | ||
if (!obj) | ||
{ | ||
rt.unterminated_error(); | ||
return ERROR; | ||
} | ||
|
||
p.end = parsed + remaining; | ||
p.out = rt.make<tag>(ID_tag, lbl, llen, obj); | ||
|
||
return p.out ? OK : ERROR; | ||
} | ||
|
||
|
||
RENDER_BODY(tag) | ||
// ---------------------------------------------------------------------------- | ||
// Render the tag into the given text buffer | ||
// ---------------------------------------------------------------------------- | ||
// When rendering on the stack, we render as "LABEL:object" | ||
// Otherwise, we render as ":LABEL:object" | ||
{ | ||
size_t llen = 0; | ||
utf8 ltxt = o->label_value(&llen); | ||
if (!r.stack()) | ||
r.put(':'); | ||
r.put(ltxt, llen); | ||
r.put(':'); | ||
|
||
object_p obj = o->tagged_object(); | ||
obj->render(r); | ||
|
||
return r.size(); | ||
} | ||
|
||
|
||
EXEC_BODY(tag) | ||
// ---------------------------------------------------------------------------- | ||
// Execution of a tagged object executes the associated object | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
object_p obj = o->tagged_object(); | ||
return obj->execute(); | ||
} | ||
|
||
|
||
COMMAND_BODY(dtag) | ||
// ---------------------------------------------------------------------------- | ||
// Remove the tag from an object | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
if (object_p obj = rt.top()) | ||
{ | ||
if (tag_p tobj = obj->as<tag>()) | ||
{ | ||
do | ||
{ | ||
obj = tobj->tagged_object(); | ||
} while ((tobj = obj->as<tag>())); | ||
if (!rt.top(obj)) | ||
return ERROR; | ||
} | ||
return OK; | ||
} | ||
return ERROR; | ||
} | ||
|
||
|
||
COMMAND_BODY(ToTag) | ||
// ---------------------------------------------------------------------------- | ||
// Build a tag object from a name and object | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
if (object_g x = rt.stack(0)) | ||
{ | ||
if (object_g y = rt.stack(1)) | ||
{ | ||
while (tag_p tagged = x->as<tag>()) | ||
x = tagged->tagged_object(); | ||
|
||
if (text_g label = x->as_text()) | ||
{ | ||
size_t lsz = 0; | ||
utf8 ltxt = label->value(&lsz); | ||
tag_g tagged = tag::make(ltxt, lsz, y); | ||
if (tagged && rt.drop() && rt.top(tagged)) | ||
return OK; | ||
} | ||
} | ||
} | ||
return ERROR; | ||
} | ||
|
||
|
||
COMMAND_BODY(FromTag) | ||
// ---------------------------------------------------------------------------- | ||
// Expand a tagged object into its value and tag | ||
// ---------------------------------------------------------------------------- | ||
{ | ||
if (object_p x = rt.top()) | ||
{ | ||
if (tag_g tagged = x->as<tag>()) | ||
{ | ||
if (rt.top(tagged->tagged_object())) | ||
{ | ||
size_t lsz = 0; | ||
utf8 ltxt = tagged->label_value(&lsz); | ||
text_p label = text::make(ltxt, lsz); | ||
if (label && rt.push(label)) | ||
return OK; | ||
} | ||
} | ||
} | ||
|
||
return ERROR; | ||
} |
Oops, something went wrong.