From 5cd2865f25096884d0d3812cc1c2d11e439144e9 Mon Sep 17 00:00:00 2001 From: Wang-Zhou Dai Date: Mon, 15 Mar 2021 19:36:47 +0800 Subject: [PATCH] fix quotenode parser --- README.md | 57 ++++++++++++++++++++++++++++++++++------------------ c/jurassic.c | 28 +++++++++++++++++--------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 04e0fcd..8748ebd 100644 --- a/README.md +++ b/README.md @@ -316,9 +316,9 @@ a = (2.0, Symbol("I''m a quoted symbol")) true. % wrong usage -?- a := tuple([2.0, :'I\'m a quoted symbol']), +?- a := tuple([2.0, :'I\'m a quoted symbol will be evaluated']), := @show(a). -UndefVarError: I''m a quoted symbol not defined +UndefVarError: I''m a quoted symbol will be evaluated not defined false. ?- a := array('Int64', undef, 2, 2). @@ -385,29 +385,26 @@ a = -2 true. ``` -__Remark__: Tuples are *always* evaluated before unification, lists are not. -When unifying `X := tuple([$a])`, the stuff in `tuple/1` will be evaluated by -Julia, so `:=/2` will try to access the value of variable `:a` or `$a` by -default: +__Remark__: Symbols in lists and tuples are *always* evaluated before +`:=/2` unification, and their behaviours are different: ``` prolog ?- a := 1. true. -?- X := [a, $a]. -X = [1, $a]. +?- X := [a, :a, $a, :(:a), $($a)]. +X = [1, 1, $1, $1, $ ($1)]. -?- X := tuple([a, :a]). -X = tuple([1, 1]). +%% behaviour of tuple is different to list +?- X := tuple([a, :a, $a, :(:a), $($a)]). +X = tuple([1, 1, 1, 1, $1]). -?- X := tuple([1+1, :a]). -X = tuple([2, 1]). +%% nothing will change under =/2 unification +?- X = [a, :a, $a, :(:a), $($a)]. +X = [a, :a, $a, : (:a), $ ($a)]. -?- X := tuple([1+1, $a]). -X = tuple([2, 1]). - -?- X := tuple([1+1, $($a)]). -X = tuple([2, $a]). +?- X = tuple([a, :a, $a, :(:a), $($a)]). +X = tuple([a, :a, $a, : (:a), $ ($a)]). ``` Keyword assignments in a function call are represented by the `kw/2` predicate: @@ -487,9 +484,23 @@ evaluate symbols in the expressions, directly assigning an atom with `Expr` will cause errors: ``` prolog +?- jl_isdefined(a). +false. + ?- e := jl_expr(:call, [+, 1, :a]). UndefVarError: a not defined false. + +%% if a is defined +?- a := 2, + e := jl_expr(:call, [+, 1, :a]). +true. + +%% instead of assigning a Expr, it assigns the evaluated results +?- := @show(e). +e = 3 +true. + ``` To assign a variable with value of Julia `Expr` via `:=/2`, please use the @@ -499,9 +510,15 @@ To assign a variable with value of Julia `Expr` via `:=/2`, please use the ?- e := $jl_expr(:call, [+, 1, :a]). true. +%% explicitly claim "+" is a symbol with :/1 ?- e := $jl_expr(:call, [:(+), 1, :a]). true. +?- := 'Meta'.show_sexpr(e), + nl. +(:call, :+, 1, :a) +true. + %% evaluate the expression e (will fail because a is not defined) ?- := @show(eval(e)). UndefVarError: a not defined @@ -568,12 +585,12 @@ A = [: (+), 1, :b]. %% unify with nested expressions ?- X1 = jl_expr(:call, [:(+), :a, 2]), - e $= jl_expr(:call, [:(*), X1, :a]). + e $= jl_expr(:call, [:(*), X1, :a]). X1 = jl_expr(:call, [: (+), :a, 2]). ?- X := e, writeln(X). -jl_expr(:call,[: (*),jl_expr(:call,[: (+),jl_expr(:call,[: (+),1,:b]),2]),jl_expr(:call,[: (+),1,:b])]) -X = jl_expr(:call, [: (*), jl_expr(:call, [: (+), jl_expr(:call, [: (+), 1|...]), 2]), jl_expr(:call, [: (+), 1, :b])]). +jl_expr(:call,[: (*),jl_expr(:call,[: (+),:a,2]),:a]) +X = jl_expr(:call, [: (*), jl_expr(:call, [: (+), :a, 2]), :a]). ``` ## TODO: Multi-dimension Arrays diff --git a/c/jurassic.c b/c/jurassic.c index 8825803..990b69d 100644 --- a/c/jurassic.c +++ b/c/jurassic.c @@ -582,8 +582,17 @@ jl_expr_t *compound_to_jl_expr(term_t expr) { printf(" Command string: %s.\n", cmd_str); #endif return (jl_expr_t *) checked_send_command_str(cmd_str); - } else if (fname[0] == ':' && arity < 2) { - return (jl_expr_t *) pl2sym(expr); + } else if (PL_is_functor(expr, FUNCTOR_quote1) && arity < 2) { + term_t expr_arg = PL_new_term_ref(); + if (!PL_get_arg(1, expr, expr_arg)) { + printf("[ERR] Reading quoted symbol failed!\n"); + return NULL; + } + if (PL_is_compound(expr_arg)) { + // QuoteNode? + return (jl_expr_t *) jl_new_struct(jl_quotenode_type, compound_to_jl_expr(expr_arg)); + } else if (PL_is_atom(expr_arg)) + return (jl_expr_t *) pl2sym(expr); } else if (PL_is_functor(expr, FUNCTOR_quotenode1) && arity < 2) { // fetch the argument term_t arg_term = PL_new_term_ref(); @@ -1239,16 +1248,17 @@ int jl_unify_pl(jl_value_t *val, term_t *ret) { return PL_unify_string_chars(tmp_term, retval); } else if (jl_is_quotenode(val)) { #ifdef JURASSIC_DEBUG - printf(" QuoteNode: "); + printf(" QuoteNode of "); #endif - const char *retval = jl_symbol_name((jl_sym_t *) jl_quotenode_value(val)); + jl_value_t *quotedval = jl_quotenode_value(val); #ifdef JURASSIC_DEBUG - printf(":%s.\n", retval); + jl_static_show(JL_STDOUT, (jl_value_t *) quotedval); + printf(".\n"); #endif - term_t qname = PL_new_term_ref(); - return PL_put_atom(qname, PL_new_atom(retval)) && - PL_unify_functor(tmp_term, FUNCTOR_quotenode1) && - PL_unify_arg(1, tmp_term, qname); + term_t qval = PL_new_term_ref(); + return jl_unify_pl(quotedval, &qval) + && PL_unify_functor(tmp_term, FUNCTOR_quotenode1) + && PL_unify_arg(1, tmp_term, qval); } else if (jl_is_symbol(val)) { #ifdef JURASSIC_DEBUG printf(" Symbol (Atom): ");