Skip to content

Commit

Permalink
Merge pull request #67 from royward/main
Browse files Browse the repository at this point in the history
Added format-args
  • Loading branch information
TeamSPoon authored Aug 14, 2024
2 parents 621387b + 56975c5 commit a0a1cf4
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/canary/metta_corelib.pl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@
metta_atom_corelib_types( [:, unify, [->, 'Atom', 'Atom', 'Atom', 'Atom', '%Undefined%']]).
metta_atom_corelib_types( [:, unify, [->, 'Atom', 'Atom', 'Atom', 'Atom', 'Atom']]).
metta_atom_corelib_types( [:, unquote, [->, '%Undefined%', '%Undefined%']]).
% metta_atom_corelib_types( [:, stringToChars [-> 'Atom' 'Expression']]).
% metta_atom_corelib_types( [:, charsToString [-> 'Expression' 'Atom']]).
% metta_atom_corelib_types( [:, format-args [-> 'Atom' 'Expression' 'Atom']]).

metta_atom_corelib_types( [:, 'get-metatype', [->, 'Atom', 'Atom']]).
metta_atom_corelib_types( [:, 'get-type0', [->, 'Atom', 'Atom']]).
Expand Down
50 changes: 50 additions & 0 deletions src/canary/metta_eval.pl
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,56 @@
eval_20(Eq,RetType,Depth,Self,['stringToChars',String],Chars):- !, eval_args(Eq,RetType,Depth,Self,String,SS), string_chars(SS,Chars0), maplist(as_metta_char,Chars0,Chars).
eval_20(Eq,RetType,Depth,Self,['charsToString',Chars],String):- !, eval_args(Eq,RetType,Depth,Self,Chars,CC), maplist(as_metta_char,CC0,CC), string_chars(String,CC0).

% =================================================================
% =================================================================
% =================================================================
% FORMAT-ARGS
% =================================================================
% =================================================================
% =================================================================

% We deal with indexing, but not formatting (the stuff following the ':')(yet)
% https://doc.rust-lang.org/std/fmt/ used as a reference

format_args_get_index([C|FormatRest1], FormatRest2, Index2) :- char_code(C, Ccode), Ccode >= 48, Ccode =< 57, !, % in the range ['0'..'9']
Index1 is Ccode-48,
format_args_get_index1(FormatRest1, FormatRest2, Index1, Index2).
format_args_get_index(FormatRest, FormatRest, none).

% have at least one digit already. This is separate from format_args_get_index to distinguish {} and {0} cases
format_args_get_index1([C|FormatRest1], FormatRest2, Index1, Index3) :- char_code(C, Ccode), Ccode >= 48, Ccode =< 57, !, % in the range ['0'..'9']
Index2 is (Index1*10)+(Ccode-48),
format_args_get_index1(FormatRest1, FormatRest2, Index2, Index3).
format_args_get_index1(FormatRest, FormatRest, Index, Index).

% Placeholder to deal with formatting {<n>:<format>} later
format_args_get_format(FormatRest, FormatRest, _).

format_args_write(Arg,_) :- string(Arg), !, write(Arg).
format_args_write('#\\'(Arg),_) :- !, write(Arg).
format_args_write(Arg,_) :- write_src_woi(Arg).

format_args([], _, _).
format_args(['{','{'|FormatRest], Iterator, Args) :- !, put('{'), format_args(FormatRest, Iterator, Args). % escaped
format_args(['}','}'|FormatRest], Iterator, Args) :- !, put('}'), format_args(FormatRest, Iterator, Args). % escaped
format_args(['{'|FormatRest1], Iterator1, Args) :-
format_args_get_index(FormatRest1, FormatRest2, Index),
format_args_get_format(FormatRest2, ['}'|FormatRest3], Format),
% check that the closing '}' is not escaped with another '}'
((FormatRest3=[] ; ((FormatRest3=[C|_],C\='}')) )),
% The Rust behaviour of advancing the iterator if an index is not specified
(((Index == none))
-> ((nth0(Iterator1,Args,Arg),Iterator2 is Iterator1+1))
; ((nth0(Index,Args,Arg), Iterator2 is Iterator1))),
format_args_write(Arg,Format),
format_args(FormatRest3, Iterator2, Args).
format_args([C|FormatRest], Iterator, Args) :- put(C), format_args(FormatRest, Iterator, Args).

eval_20(Eq,RetType,Depth,Self,['format-args',Format,Args],Result):- !,
eval_args(Eq,RetType,Depth,Self,Format,EFormat),
eval_args(Eq,RetType,Depth,Self,Args,EArgs),
string_chars(EFormat, FormatChars), user_io(with_output_to(string(Result), format_args(FormatChars, 0, EArgs))).
% string_chars(EFormat, FormatChars), wots(Result, format_args(FormatChars, 0, EArgs)).

eval_20(Eq,RetType,_Depth,_Self,['flip'],Bool):-
ignore(RetType='Bool'), !, as_tf(random(0,2,0),Bool),
Expand Down
1 change: 1 addition & 0 deletions src/canary/metta_interp.pl
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@
% conversion between String and List of Chars
'stringToChars'(String, Chars) :- eval_H(['stringToChars', String], Chars).
'charsToString'(Chars, String) :- eval_H(['charsToString', Chars], String).
'format-args'(Format, Args, Result) :- eval_H(['format-args', Format, Args], Result).

% ============================
% %%%% Random Utilities
Expand Down
1 change: 1 addition & 0 deletions src/canary/metta_ontology.pfc.pl
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,5 @@
% --- String and Character manipulation ---
properties('&corelib','stringToChars', [string_operations, qhelp("Convert a string to a list of chars."), string_to_chars]).
properties('&corelib','charsToString', [string_operations, qhelp("Convert a list of chars to a string."), chars_to_string]).
properties('&corelib','format-args', [string_operations, qhelp("Generate a formatted string using a format specifier."), format_args]).
properties('&corelib','flip', [random, qhelp("Return a random boolean."), random_boolean]).
25 changes: 25 additions & 0 deletions tests/baseline_compat/hyperon-mettalog_sanity/string-tests.metta
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
;; String <=> List of Characters

!(assertEqual (stringToChars "xyzzy") ('x' 'y' 'z' 'z' 'y'))

!(assertEqual (charsToString ('x' 'y' 'z' 'z' 'y')) "xyzzy")
Expand All @@ -21,3 +23,26 @@
!(assertEqual (stringToChars " ") (' '))

!(assertEqual (stringToChars (superpose ("ab" "cd" "ef"))) (superpose (('a' 'b') ('c' 'd') ('e' 'f'))))

;; format-args

!(assertEqual (format-args "" (1 2 3)) "")

!(assertEqual (format-args " " (1 2 3)) " ")

!(assertEqual (format-args "{}" (1 2 3)) "1")

!(assertEqual (format-args "{}}" (1 2 3)) "{}")

!(assertEqual (format-args "xyz zy" (1 2 3)) "xyz zy")

!(assertEqual (format-args "Indexed {1} {} {0} {}" (1 2 3)) "Indexed 2 1 1 2")

!(assertEqual (format-args "Different types {} {} {} {} {} {}" (1 "2" 'c' -0.5 atom (1 2 c -0.5 atom))) "Different types 1 2 c -0.5 atom (1 2 c -0.5 atom)")

!(assertEqual (format-args "Two digit index={11}" (0 1 2 3 4 5 6 7 8 9 10 "eleven")) "Two digit index=eleven")

;; malformed examples
!(assertEqual (format-args "Bad args list {1} {} {0} {}" x) "Bad args list {1} {} {0} {}")

!(assertEqual (format-args "Malformed format}{{}{{{}{} {4} { } {-1} {x} {{{{{{}}}}}}{{{{{}}}}}" ("success1" "success2")) "Malformed format}{}{success1success2 {4} { } {-1} {x} {{{}}}{{{}}}")
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]
[()]

0 comments on commit a0a1cf4

Please sign in to comment.