rpl: Implement Compile (aka STR→)

Implement the `Compile` command, which evaluates a text as if
it was on the command line.

Fixes: #590

Signed-off-by: Christophe de Dinechin <christophe@dinechin.org>
This commit is contained in:
Christophe de Dinechin 2023-11-21 22:18:24 +01:00
parent e5334be66e
commit 5646ce709e
9 changed files with 302 additions and 238 deletions

View file

@ -179,7 +179,8 @@ The following is a list of the HP50 RPL commands which are implemented in DB48X.
* [→LIST](#tolist)
* [→NUM](#todecimal)
* [→Q](#tofraction)
* [→STR](#→str)
* [→STR](#totext)
* [STR→](#compile)
* [→TAG](#→tag)
* [→UNIT](#→unit)
* [](#locals) (Create Local)
@ -687,7 +688,6 @@ commands.
* STO*
* STO/
* STOΣ
* STR→
* STREAM
* STRM
* STURM

View file

@ -1,4 +1,5 @@
# Operations with Strings
# Operations on text
## TOUTF
Create a Utf8 string from a list of code points
@ -8,12 +9,15 @@ Create a Utf8 string from a list of code points
List all code points in a Utf8 string
## TOSTR
Decompile any object (convert to string)
## ToText (→STR, →TEXT)
Convert an object to its text representation.
## FROMSTR
Compile a string into RPL objects
## Compile (STR→, TEXT→)
Compile and evaluate the text, as if it was typed on the command line.
`"1 2 + 4" TEXT→` will push `3` and `4` on the stack.
## SREV
@ -62,4 +66,3 @@ Decompile formatted for display
## TOEDITSTR
Decompile formatted for edit

View file

@ -2100,7 +2100,8 @@ The following is a list of the HP50 RPL commands which are implemented in DB48X.
* [→LIST](#tolist)
* [→NUM](#todecimal)
* [→Q](#tofraction)
* [→STR](#→str)
* [→STR](#totext)
* [STR→](#compile)
* [→TAG](#→tag)
* [→UNIT](#→unit)
* [](#locals) (Create Local)
@ -2608,7 +2609,6 @@ commands.
* STO*
* STO/
* STOΣ
* STR→
* STREAM
* STRM
* STURM
@ -5775,71 +5775,6 @@ Set both the independent and dependent data columns in the reserved variable
`ΣParameters`.
`XCol` `YCol` ▶ (Update `ΣParameters`)
# Operations with Strings
## TOUTF
Create a Utf8 string from a list of code points
## FROMUTF
List all code points in a Utf8 string
## TOSTR
Decompile any object (convert to string)
## FROMSTR
Compile a string into RPL objects
## SREV
Reverse the characters on a string
## NTOKENS
Number of tokens in a string
## NTHTOKEN
Token at position N in a string
## NTHTOKENPOS
Position of token N in a string
## TRIM
Remove characters at end of string
## RTRIM
Remove characters at start of string
## SSTRLEN
Length of string in characters
## STRLENCP
Length of string in Unicode code points
## TONFC
Normalize a string to Unicode NFC
## SREPL
Find and replace text in a string
## TODISPSTR
Decompile formatted for display
## TOEDITSTR
Decompile formatted for edit
# Operations with Symbolic Expressions
## Rewrite
@ -6141,6 +6076,74 @@ For example, `:Hello:1 Tag→` results in `"Hello"` in level 1 and `1` in level
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.
# Operations on text
## TOUTF
Create a Utf8 string from a list of code points
## FROMUTF
List all code points in a Utf8 string
## ToText (→STR, →TEXT)
Convert an object to its text representation.
## Compile (STR→, TEXT→)
Compile and evaluate the text, as if it was typed on the command line.
`"1 2 + 4" TEXT→` will push `3` and `4` on the stack.
## SREV
Reverse the characters on a string
## NTOKENS
Number of tokens in a string
## NTHTOKEN
Token at position N in a string
## NTHTOKENPOS
Position of token N in a string
## TRIM
Remove characters at end of string
## RTRIM
Remove characters at start of string
## SSTRLEN
Length of string in characters
## STRLENCP
Length of string in Unicode code points
## TONFC
Normalize a string to Unicode NFC
## SREPL
Find and replace text in a string
## TODISPSTR
Decompile formatted for display
## TOEDITSTR
Decompile formatted for edit
# Transcendental functions
## SIN

View file

@ -2100,7 +2100,8 @@ The following is a list of the HP50 RPL commands which are implemented in DB50X.
* [→LIST](#tolist)
* [→NUM](#todecimal)
* [→Q](#tofraction)
* [→STR](#→str)
* [→STR](#totext)
* [STR→](#compile)
* [→TAG](#→tag)
* [→UNIT](#→unit)
* [](#locals) (Create Local)
@ -2608,7 +2609,6 @@ commands.
* STO*
* STO/
* STOΣ
* STR→
* STREAM
* STRM
* STURM
@ -5775,71 +5775,6 @@ Set both the independent and dependent data columns in the reserved variable
`ΣParameters`.
`XCol` `YCol` ▶ (Update `ΣParameters`)
# Operations with Strings
## TOUTF
Create a Utf8 string from a list of code points
## FROMUTF
List all code points in a Utf8 string
## TOSTR
Decompile any object (convert to string)
## FROMSTR
Compile a string into RPL objects
## SREV
Reverse the characters on a string
## NTOKENS
Number of tokens in a string
## NTHTOKEN
Token at position N in a string
## NTHTOKENPOS
Position of token N in a string
## TRIM
Remove characters at end of string
## RTRIM
Remove characters at start of string
## SSTRLEN
Length of string in characters
## STRLENCP
Length of string in Unicode code points
## TONFC
Normalize a string to Unicode NFC
## SREPL
Find and replace text in a string
## TODISPSTR
Decompile formatted for display
## TOEDITSTR
Decompile formatted for edit
# Operations with Symbolic Expressions
## Rewrite
@ -6141,6 +6076,74 @@ For example, `:Hello:1 Tag→` results in `"Hello"` in level 1 and `1` in level
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.
# Operations on text
## TOUTF
Create a Utf8 string from a list of code points
## FROMUTF
List all code points in a Utf8 string
## ToText (→STR, →TEXT)
Convert an object to its text representation.
## Compile (STR→, TEXT→)
Compile and evaluate the text, as if it was typed on the command line.
`"1 2 + 4" TEXT→` will push `3` and `4` on the stack.
## SREV
Reverse the characters on a string
## NTOKENS
Number of tokens in a string
## NTHTOKEN
Token at position N in a string
## NTHTOKENPOS
Position of token N in a string
## TRIM
Remove characters at end of string
## RTRIM
Remove characters at start of string
## SSTRLEN
Length of string in characters
## STRLENCP
Length of string in Unicode code points
## TONFC
Normalize a string to Unicode NFC
## SREPL
Find and replace text in a string
## TODISPSTR
Decompile formatted for display
## TOEDITSTR
Decompile formatted for edit
# Transcendental functions
## SIN

View file

@ -283,6 +283,39 @@ COMMAND_BODY(ToText)
}
COMMAND_BODY(Compile)
// ----------------------------------------------------------------------------
// Interpret the object as a command line and evaluate it
// ----------------------------------------------------------------------------
{
if (rt.args(1))
{
if (object_p obj = rt.top())
{
if (text_p tobj = obj->as<text>())
{
size_t len = 0;
utf8 txt = tobj->value(&len);
program_g cmds = program::parse(txt, len);
if (cmds)
{
// We successfully parsed the line, execute it
rt.drop();
save<bool> no_halt(program::halted, false);
if (cmds->run(false))
return OK;
}
}
else
{
rt.type_error();
}
}
}
return ERROR;
}
COMMAND_BODY(SelfInsert)
// ----------------------------------------------------------------------------
// Find the label associated to the menu and enter it in the editor
@ -621,80 +654,6 @@ COMMAND_BODY(Help)
}
COMMAND_BODY(ToolsMenu)
// ----------------------------------------------------------------------------
// Contextual tool menu
// ----------------------------------------------------------------------------
{
id menu = ID_MainMenu;
if (rt.editing())
{
switch(ui.editing_mode())
{
case ui.DIRECT: menu = ID_MathMenu; break;
case ui.TEXT: menu = ID_TextMenu; break;
case ui.PROGRAM: menu = ID_ProgramMenu; break;
case ui.ALGEBRAIC: menu = ID_EquationsMenu; break;
case ui.MATRIX: menu = ID_MatrixMenu; break;
case ui.BASED: menu = ID_BasesMenu; break;
default:
case ui.STACK: break;
}
}
else if (rt.depth())
{
if (!rt.args(1))
return ERROR;
if (object_p top = rt.top())
{
switch(top->type())
{
case ID_integer:
case ID_neg_integer:
case ID_bignum:
case ID_neg_bignum:
case ID_decimal128:
case ID_decimal64:
case ID_decimal32: menu = ID_RealMenu; break;
case ID_fraction:
case ID_neg_fraction:
case ID_big_fraction:
case ID_neg_big_fraction: menu = ID_FractionsMenu; break;
case ID_polar:
case ID_rectangular: menu = ID_ComplexMenu; break;
#if CONFIG_FIXED_BASED_OBJECTS
case ID_hex_integer:
case ID_dec_integer:
case ID_oct_integer:
case ID_bin_integer:
case ID_hex_bignum:
case ID_dec_bignum:
case ID_oct_bignum:
case ID_bin_bignum:
#endif // CONFIG_FIXED_BASED_OBJECTS
case ID_based_integer:
case ID_based_bignum: menu = ID_BasesMenu; break;
case ID_expression: menu = ID_SymbolicMenu; break;
case ID_program: menu = ID_DebugMenu; break;
case ID_list: menu = ID_ListMenu; break;
case ID_array: menu = ID_MatrixMenu; break;
case ID_tag: menu = ID_ObjectMenu; break;
case ID_unit: menu = ID_UnitsConversionsMenu; break;
default: break;
}
}
}
else if (!rt.args(0))
{
return ERROR;
}
object_p obj = command::static_object(menu);
return obj->evaluate();
}
COMMAND_BODY(Cycle)
// ----------------------------------------------------------------------------
// Cycle object across multiple representations
@ -902,18 +861,6 @@ COMMAND_BODY(RealToBinary)
}
COMMAND_BODY(LastMenu)
// ----------------------------------------------------------------------------
// Go back one entry in the menu history
// ----------------------------------------------------------------------------
{
if (!rt.args(0))
return ERROR;
ui.menu_pop();
return OK;
}
COMMAND_BODY(LastArg)
// ----------------------------------------------------------------------------
// Return the last arguments

View file

@ -129,6 +129,8 @@ struct Unimplemented : command
// Various global commands
COMMAND_DECLARE(Eval); // Evaluate an object
COMMAND_DECLARE(Compile); // Compile and evalaute a text
//COMMAND_DECLARE(Explode); // Explode an object
COMMAND_DECLARE(ToText); // Convert an object to text
COMMAND_DECLARE(SelfInsert); // Enter menu label in the editor
COMMAND_DECLARE(Ticks); // Return number of ticks
@ -146,8 +148,6 @@ COMMAND_DECLARE(Help); // Activate online help
COMMAND_DECLARE(LastArg); // Return last arguments
COMMAND_DECLARE(LastX); // Return last X argument
COMMAND_DECLARE(Undo); // Revert to the Undo stack
COMMAND_DECLARE(ToolsMenu); // Automatic selection of the right menu
COMMAND_DECLARE(LastMenu); // Return to previous menu
COMMAND_DECLARE(Cycle); // Cycle object across multiple representations
COMMAND_DECLARE(BinaryToReal); // Convert binary to real
COMMAND_DECLARE(RealToBinary); // Convert real to binary

View file

@ -198,8 +198,7 @@ CMD(Purge)
// Evaluation and rendering
NAMED(Eval, "Evaluate")
NAMED(ToText, "→Text")
ALIAS(ToText, "→Str")
NAMED(ToText, "→Text") ALIAS(ToText, "ToStr") ALIAS(ToText, "→Str")
// Constants
NAMED(pi, "π")
@ -297,6 +296,7 @@ CMD(CaseWhen)
// Data processing
NAMED(ToList, "→List")
NAMED(FromList, "List→")
// NAMED(Explode, "Object→") ALIAS(Explode, "Obj→")
CMD(Get)
CMD(Size)
CMD(Sort)
@ -304,10 +304,10 @@ CMD(Sort)
// Tests
NAMED(IFT, "IfThen")
NAMED(IFTE, "IfThenElse")
CMD(SetFlag) ALIAS(SetFlag, "SF")
CMD(ClearFlag) ALIAS(ClearFlag, "CF")
CMD(TestFlagSet) ALIAS(TestFlagSet, "FS?")
CMD(TestFlagClear) ALIAS(TestFlagClear, "FC?")
CMD(SetFlag) ALIAS(SetFlag, "SF")
CMD(ClearFlag) ALIAS(ClearFlag, "CF")
CMD(TestFlagSet) ALIAS(TestFlagSet, "FS?")
CMD(TestFlagClear) ALIAS(TestFlagClear, "FC?")
// Graphics
NAMED(Disp, "DrawText")
@ -426,6 +426,9 @@ CMD(FreeMemory)
CMD(SystemMemory)
CMD(GarbageCollect)
// Object commands
NAMED(Compile, "Text→") ALIAS(Compile, "Str→")
// Flags
CMD(FlipFlag) ALIAS(FlipFlag, "FF")
CMD(TestFlagClearThenClear) ALIAS(TestFlagClearThenClear, "FC?C")

View file

@ -171,6 +171,100 @@ void menu::items(info &mi, cstring label, object_p action)
// ============================================================================
//
// Commands related to menus
//
// ============================================================================
COMMAND_BODY(ToolsMenu)
// ----------------------------------------------------------------------------
// Contextual tool menu
// ----------------------------------------------------------------------------
{
id menu = ID_MainMenu;
if (rt.editing())
{
switch(ui.editing_mode())
{
case ui.DIRECT: menu = ID_MathMenu; break;
case ui.TEXT: menu = ID_TextMenu; break;
case ui.PROGRAM: menu = ID_ProgramMenu; break;
case ui.ALGEBRAIC: menu = ID_EquationsMenu; break;
case ui.MATRIX: menu = ID_MatrixMenu; break;
case ui.BASED: menu = ID_BasesMenu; break;
default:
case ui.STACK: break;
}
}
else if (rt.depth())
{
if (!rt.args(1))
return ERROR;
if (object_p top = rt.top())
{
switch(top->type())
{
case ID_integer:
case ID_neg_integer:
case ID_bignum:
case ID_neg_bignum:
case ID_decimal128:
case ID_decimal64:
case ID_decimal32: menu = ID_RealMenu; break;
case ID_fraction:
case ID_neg_fraction:
case ID_big_fraction:
case ID_neg_big_fraction: menu = ID_FractionsMenu; break;
case ID_polar:
case ID_rectangular: menu = ID_ComplexMenu; break;
#if CONFIG_FIXED_BASED_OBJECTS
case ID_hex_integer:
case ID_dec_integer:
case ID_oct_integer:
case ID_bin_integer:
case ID_hex_bignum:
case ID_dec_bignum:
case ID_oct_bignum:
case ID_bin_bignum:
#endif // CONFIG_FIXED_BASED_OBJECTS
case ID_based_integer:
case ID_based_bignum: menu = ID_BasesMenu; break;
case ID_text: menu = ID_TextMenu; break;
case ID_expression: menu = ID_SymbolicMenu; break;
case ID_program: menu = ID_DebugMenu; break;
case ID_list: menu = ID_ListMenu; break;
case ID_array: menu = ID_MatrixMenu; break;
case ID_tag: menu = ID_ObjectMenu; break;
case ID_unit: menu = ID_UnitsConversionsMenu; break;
default: break;
}
}
}
else if (!rt.args(0))
{
return ERROR;
}
object_p obj = command::static_object(menu);
return obj->evaluate();
}
COMMAND_BODY(LastMenu)
// ----------------------------------------------------------------------------
// Go back one entry in the menu history
// ----------------------------------------------------------------------------
{
if (!rt.args(0))
return ERROR;
ui.menu_pop();
return OK;
}
// ============================================================================
//
// Creation of a menu
@ -1337,7 +1431,7 @@ MENU(TextMenu,
// Text operations
// ----------------------------------------------------------------------------
"→Text", ID_ToText,
"Text→", ID_Unimplemented,
"Length", ID_Unimplemented,
"Text→", ID_Compile,
"Length", ID_Size,
"Append", ID_add,
"Repeat", ID_mul);

View file

@ -208,4 +208,15 @@ struct SysMenu : menu \
#include "ids.tbl"
// ============================================================================
//
// Commands related to menus
//
// ============================================================================
COMMAND_DECLARE(LastMenu); // Return to previous menu
COMMAND_DECLARE(ToolsMenu); // Automatic selection of the right menu
#endif // MENU_H