poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 11/12] libpoke: Add `format`


From: Jose E. Marchesi
Subject: Re: [PATCH 11/12] libpoke: Add `format`
Date: Sat, 29 May 2021 10:10:57 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

Hi Mohammad.

As agreed this review covers the code generation part and not the AST
and other compiler phases.

> diff --git a/libpoke/pkl-gen.c b/libpoke/pkl-gen.c
> index 19d7fb9e..4abe18d7 100644
> --- a/libpoke/pkl-gen.c
> +++ b/libpoke/pkl-gen.c
> @@ -1408,6 +1408,192 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_exp_stmt)
>  }
>  PKL_PHASE_END_HANDLER
>  
> +/*
> + * FORMAT
> + * | ARG
> + * | ...
> + */
> +
> +PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_format)
> +{

  [...]

> +      /* Set the argument's own omode and odepth, saving
> +         the VM's own.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOM); /* OMODE */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                    pvm_make_int (arg_omode, 32)); /* OMODE NOMODE */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM);  /* OMODE */
> +
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSHOD); /* OMODE ODEPTH */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                    pvm_make_int (arg_odepth, 32)); /* OMODE ODEPTH NODEPTH 
> */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD);   /* OMODE ODEPTH */
> +
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_ROT); /* OMODE ODEPTH EXP */

I think this can be factored into a macro (maybe a macro-instruction?)
and used in both PRINT_STMT and FORMAT.

> +
> +      /* Format the value.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                    pvm_make_int (0, 32)); /* OMODE ODEPTH EXP DEPTH */
> +      PKL_GEN_DUP_CONTEXT;
> +      PKL_GEN_SET_CONTEXT (PKL_GEN_CTX_IN_FORMATER);
> +      PKL_PASS_SUBPASS (exp_type); /* OMODE ODEPTH STR */
> +      PKL_GEN_POP_CONTEXT;

It is generally more robust to push a new empty context than reusing the
existing one:

PKL_GEN_PUSH_CONTEXT;
PKL_GEN_SET_CONTEXT (PKL_GEN_CTX_IN_FORMATER);
[...]
PKL_GEN_POP_CONTEXT;

> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_NROT); /* STR OMODE ODEPTH */
> +
> +      /* Restore the current omode and odepth in the VM.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOD); /* ARR STR OMODE */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_POPOM); /* ARR STR */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                    pvm_make_ulong (nstr++, 64)); /* ARR STR IDX */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_SWAP);  /* ARR IDX STR */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_AINS);  /* ARR */

This can also be factored.

> +    fmt_suffix:
> +      if (suffix)
> +        {
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, pvm_make_ulong (nstr++, 
> 64));
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, pvm_make_string 
> (suffix));
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_AINS);
> +        }
> +    }
> +
> +  if (nstr)
> +    {
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DUP);
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, pvm_make_ulong (0, 64));
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, pvm_make_ulong (nstr, 64));
> +      pkl_asm_call (PKL_GEN_ASM, "_pkl_reduce_string_array");
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_NIP);
> +    }
> +
> +  PKL_PASS_BREAK;
> +
> +#undef MAX_CLASS_TAGS
> +}
> +PKL_PHASE_END_HANDLER
> +
>  /*
>   * PRINT_STMT
>   * | ARG
> @@ -1985,6 +2171,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_offset)
>        RAS_MACRO_OFFSET_PRINTER (PKL_PASS_NODE); /* _ */
>        PKL_PASS_BREAK;
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +                                                /* VAL DEPTH */
> +      RAS_MACRO_OFFSET_FORMATER (PKL_PASS_NODE); /* _ */
> +      PKL_PASS_BREAK;
> +    }
>    else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_TYPE))
>      {
>      /* Just build an offset type.  */
> @@ -2735,6 +2927,11 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_type_integral)
>                                                    /* VAL DEPTH */
>        RAS_MACRO_INTEGRAL_PRINTER (PKL_PASS_NODE); /* _ */
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +                                                  /* VAL DEPTH */
> +      RAS_MACRO_INTEGRAL_FORMATER (PKL_PASS_NODE); /* _ */
> +    }
>    else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_TYPE))
>      {
>        pkl_asm_insn (pasm, PKL_INSN_PUSH,
> @@ -2849,6 +3046,15 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_function)
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PRINTS);
>        PKL_PASS_BREAK;
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +      /* Stack: VAL DEPTH  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP); /* DEPTH is not used.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_DROP);

VAL is also not used.

> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH,
> +                    pvm_make_string ("#<closure>"));
> +      PKL_PASS_BREAK;
> +    }
>  }
>  PKL_PHASE_END_HANDLER
>  
> @@ -3090,6 +3296,27 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_array)
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
>        PKL_PASS_BREAK;
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +      /* Stack: ARR DEPTH */
> +
> +      pkl_ast_node array_type = PKL_PASS_NODE;
> +      pvm_val formater_closure = PKL_AST_TYPE_A_FORMATER (array_type);
> +
> +      /* If the array type doesn't have a formater, compile one.  */
> +      if (formater_closure == PVM_NULL)
> +        {
> +          RAS_FUNCTION_ARRAY_FORMATER (formater_closure, array_type);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
> +        }
> +      else
> +        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);

I think the `else' part of that will never be executed.  This is
because:

1) You are not setting the compiled formatter_closure in the AST node
   after compiling it, and

2) You are not compiling formaters for named array and struct types in
   pkl_gen_pr_decl.

> +      /* Invoke the formater.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
> +      PKL_PASS_BREAK;
> +    }
>    else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_CONSTRUCTOR))
>      {
>        /* Stack: null */
> @@ -3246,6 +3473,11 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_ps_type_string)
>        /* Stack: VAL DEPTH */
>        RAS_MACRO_STRING_PRINTER; /* _ */
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +      /* Stack: VAL DEPTH */
> +      RAS_MACRO_STRING_FORMATER; /* _ */
> +    }
>    else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_TYPE))
>      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_MKTYS);
>  }
> @@ -3490,6 +3722,27 @@ PKL_PHASE_BEGIN_HANDLER (pkl_gen_pr_type_struct)
>        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
>        PKL_PASS_BREAK;
>      }
> +  else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_FORMATER))
> +    {
> +      /* Stack: SCT DEPTH */
> +
> +      pkl_ast_node struct_type = PKL_PASS_NODE;
> +      pvm_val formater_closure = PKL_AST_TYPE_S_FORMATER (struct_type);
> +
> +      /* If the struct type doesn't have a formater, compile one.  */
> +      if (formater_closure == PVM_NULL)
> +        {
> +          RAS_FUNCTION_STRUCT_FORMATER (formater_closure, struct_type);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
> +          pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PEC);
> +        }
> +      else
> +        pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_PUSH, formater_closure);
> +
> +      /* Invoke the formater.  */
> +      pkl_asm_insn (PKL_GEN_ASM, PKL_INSN_CALL); /* _ */
> +      PKL_PASS_BREAK;
> +    }
>    else if (PKL_GEN_IN_CTX_P (PKL_GEN_CTX_IN_TYPE))
>      {
>        /* Do nothing.  See PS hook.  */
> @@ -4263,6 +4516,7 @@ struct pkl_phase pkl_phase_gen =
>     PKL_PHASE_PR_HANDLER (PKL_AST_RETURN_STMT, pkl_gen_pr_return_stmt),
>     PKL_PHASE_PS_HANDLER (PKL_AST_RETURN_STMT, pkl_gen_ps_return_stmt),
>     PKL_PHASE_PS_HANDLER (PKL_AST_EXP_STMT, pkl_gen_ps_exp_stmt),
> +   PKL_PHASE_PR_HANDLER (PKL_AST_FORMAT, pkl_gen_pr_format),
>     PKL_PHASE_PR_HANDLER (PKL_AST_PRINT_STMT, pkl_gen_pr_print_stmt),
>     PKL_PHASE_PS_HANDLER (PKL_AST_RAISE_STMT, pkl_gen_ps_raise_stmt),
>     PKL_PHASE_PR_HANDLER (PKL_AST_TRY_CATCH_STMT, pkl_gen_pr_try_catch_stmt),
> diff --git a/libpoke/pkl-gen.h b/libpoke/pkl-gen.h
> index 49330460..7147113e 100644
> --- a/libpoke/pkl-gen.h
> +++ b/libpoke/pkl-gen.h
> @@ -111,6 +111,7 @@ typedef struct pkl_gen_payload *pkl_gen_payload;
>  #define PKL_GEN_CTX_IN_ARRAY_BOUNDER 0x80
>  #define PKL_GEN_CTX_IN_FUNCALL      0x200
>  #define PKL_GEN_CTX_IN_TYPE         0x400
> +#define PKL_GEN_CTX_IN_FORMATER     0x800
>  
>  extern struct pkl_phase pkl_phase_gen;
>  
> diff --git a/libpoke/pkl-gen.pks b/libpoke/pkl-gen.pks
> index 1bd48fd1..60a93d44 100644
> --- a/libpoke/pkl-gen.pks
> +++ b/libpoke/pkl-gen.pks
> @@ -1767,6 +1767,557 @@
>          drop                    ; _
>          .end
>  
> +;;; RAS_MACRO_FORMAT_INT_SUFFIX @type
> +;;; ( -- STR )
> +;;;
> +;;; Push the suffix corresponding to the specified integral type
> +;;; to the stack.
> +;;;
> +;;; Macro-arguments:
> +;;; @type
> +;;;   pkl_ast_node with an integral type.
> +
> +        .macro format_int_suffix @type
> +        .let #signed_p = pvm_make_int (PKL_AST_TYPE_I_SIGNED_P (@type), 32)
> +        .let #size = pvm_make_ulong (PKL_AST_TYPE_I_SIZE (@type), 64)
> +        push #signed_p
> +        push #size
> +        .call _pkl_format_int_suffix
> +        .end
> +
> +;;; RAS_MACRO_INTEGRAL_FORMATER @type
> +;;; ( VAL DEPTH -- STR )
> +;;;
> +;;; Given an integral value and a depth in the stack, push the
> +;;; string representation to the stack.
> +;;;
> +;;; Macro-arguments:
> +;;; @type
> +;;;   pkl_ast_node with the type of the value in the stack.
> +
> +        .macro integral_formater @type
> +        drop                    ; VAL
> +        pushob                  ; VAL OBASE
> +        ;; Calculate and format the prefix.
> +        dup                     ; VAL OBASE OBASE
> +        .call _pkl_base_prefix  ; VAL OBASE PREFIX
> +        nrot                    ; PREFIX VAL OBASE
> +        ;; Format the value.
> +        format @type            ; PREFIX STR
> +        ;; Push the suffix
> +        .e format_int_suffix @type ; PREFIX STR SUFFIX
> +        .call _pkl_strcat3      ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "integer"          ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        .end
> +
> +;;; RAS_MACRO_OFFSET_FORMATER @type
> +;;; ( VAL DEPTH -- STR )
> +;;;
> +;;; Given an offset value in the stack and a depth level,
> +;;; push the string representation of the offset to the stack.
> +;;;
> +;;; Macro-arguments:
> +;;; @type
> +;;;   pkl_ast_node with the type of the value in the stack.
> +
> +        .macro offset_formater @type
> +        ;; Format the offset magnitude
> +        .let @unit = PKL_AST_TYPE_O_UNIT (@type)
> +        .let @base_type = PKL_AST_TYPE_O_BASE_TYPE (@type)
> +        swap                    ; DEPTH VAL
> +        ogetm                   ; DEPTH VAL MAG
> +        rot                     ; VAL MAG DEPTH
> +        .c PKL_PASS_SUBPASS (@base_type);
> +                                ; VAL STR
> +        ;; Separator
> +        push "#"                ; VAL STR #
> +        rot                     ; STR # VAL
> +        ;; Format the offset unit.
> +        ;; If the unit has a name, use it.
> +        ;; Otherwise, format the unit in decimal.
> +        .let @unit_type = PKL_AST_TYPE (@unit)
> +        ogetu                   ; STR # VAL UNIT
> +        nip                     ; STR # UNIT
> +        dup                     ; STR # UNIT UNIT
> +        .call _pkl_unit_name    ; STR # UNIT STR
> +        sel                     ; STR # UNIT STR SEL
> +        bzlu .no_unit_name
> +        drop                    ; STR # UNIT STR
> +        nip                     ; STR # STR
> +        ba .unit_name_done
> +.no_unit_name:
> +        drop2                   ; STR # UNIT
> +        push int<32>10          ; STR # UNIT 10
> +        format @unit_type       ; STR # STR
> +.unit_name_done:
> +        .call _pkl_strcat3      ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "offset"           ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        .end
> +
> +;;; RAS_MACRO_STRING_FORMATER
> +;;; ( VAL DEPTH -- STR )
> +;;;
> +;;; Given a string value and a depth in the stack, push the
> +;;; the string representation to the stack.
> +
> +        .macro string_formater
> +        drop                    ; VAL
> +        .call _pkl_escape_string; VAL
> +        push "\""               ; VAL "
> +        swap                    ; " VAL
> +        push "\""               ; " VAL "
> +        .call _pkl_strcat3      ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "offset"           ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        .end
> +
> +;;; RAS_MACRO_FORMAT_BOFFSET
> +;;; ( ULONG -- STR )
> +;;;
> +;;; Given a bit-offset in the stack, format it out like a real
> +;;; offset in hexadecimal, and push it to the stack .
> +
> +        .macro format_boffset
> +        push int<32>16          ; ULONG 16
> +        formatlu 64             ; STR
> +        push "0x"
> +        swap                    ; 0x STR
> +        sconc
> +        nip2                    ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "integer"          ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        ;; XXX RAS turns "#b" into "(B_arg)"
> +        push "#"                ; STR #
> +        push "b"                ; STR # b

I wonder, we can use a C string escape character to encode either the #
or the `b' and avoid the extra `push' (this also applies to the
printer.)

> +        .call _pkl_strcat3      ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "offset"           ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        .end
> +
> +;;; RAS_FUNCTION_ARRAY_FORMATER @array_type
> +;;; ( ARR DEPTH -- STR )
> +;;;
> +;;; Assemble a function that gets an array value and a depth
> +;;; level in the stack and formats the array and push it to
> +;;; the stack.
> +;;;
> +;;; Macro-arguments:
> +;;; @array_type
> +;;;   pkl_ast_node with the type of the array value to print.
> +
> +        .function array_formater @array_type
> +        prolog
> +        pushf 1
> +        regvar $depth           ; ARR
> +        sel                     ; ARR SEL
> +        dup
> +        regvar $sel
> +        ;; Find the number of elems that will be formated: NELEM
> +        pushoac                 ; ARR SEL OACUTOFF
> +        bzi .no_cut_off
> +        itolu 64
> +        nip                     ; ARR SEL OACUTOFFL
> +        ltlu                    ; ARR SEL OACUTOFFL (SEL<OACUTOFFL)
> +        bzi .sel_gte_cutoff
> +        nrot                    ; ARR (SEL<OACUTOFFL) SEL OACUTOFFL
> +.sel_gte_cutoff:
> +        drop
> +        nip                     ; ARR NELEM
> +        push null
> +.no_cut_off:
> +        drop                    ; ARR NELEM
> +        dup
> +        regvar $nelem           ; ARR NELEM
> +        pushvar $sel
> +        eqlu
> +        nip2                    ; ARR (NELEM==SEL)
> +        regvar $no_ellip        ; ARR
> +        mktys
> +        push null
> +        mktya                   ; ARR TYPA
> +        push ulong<64>0
> +        mka                     ; ARR SARR
> +        push ulong<64>0
> +        push "["
> +        ains
> +        swap                    ; SARR ARR
> +        ;; Iterate on the values stored in the array, formating them
> +        ;; in turn.
> +        push ulong<64>0         ; SARR ARR IDX
> +        dup
> +        ;; Temporary variable.
> +        regvar $idx
> +     .while
> +        pushvar $nelem          ; SARR ARR IDX NELEM
> +        over                    ; SARR ARR IDX NELEM IDX
> +        swap                    ; SARR ARR IDX IDX NELEM
> +        ltlu                    ; SARR ARR IDX IDX NELEM (IDX<NELEM)
> +        nip2                    ; SARR ARR IDX (IDX<NELEM)
> +     .loop
> +        ;; Insert a comma if this is not the first element of the
> +        ;; array.
> +        push ulong<64>0         ; SARR ARR IDX 0UL
> +        eql
> +        nip                     ; SARR ARR IDX (IDX==0UL)
> +        bnzi .l1
> +        drop                    ; SARR ARR IDX
> +        rot                     ; ARR IDX SARR
> +        sel
> +        push ","
> +        ains                    ; ARR IDX SARR
> +        nrot                    ; SARR ARR IDX
> +        push null
> +.l1:
> +        drop                    ; SARR ARR IDX
> +        ;; Now format the array element.
> +        .let @array_elem_type = PKL_AST_TYPE_A_ETYPE (@array_type)
> +        aref                    ; SARR ARR IDX EVAL
> +        pushvar $depth          ; SARR ARR IDX EVAL DEPTH
> +        .c PKL_PASS_SUBPASS (@array_elem_type);
> +                                ; SARR ARR IDX STR
> +        swap
> +        popvar $idx             ; SARR ARR STR
> +        rot                     ; ARR STR SARR
> +        sel
> +        rot                     ; ARR SARR SEL STR
> +        ains
> +        swap                    ; SARR ARR
> +        pushvar $idx
> +        ;; Format the element offset if required.
> +        pushoo                  ; SARR ARR IDX OMAPS
> +        bzi .l3
> +        drop
> +        rot                     ; ARR IDX SARR
> +        sel                     ; ARR IDX SARR SLEN
> +        push " @ "
> +        ains                    ; ARR IDX SARR
> +        nrot                    ; SARR ARR IDX
> +        arefo                   ; SARR ARR IDX BOFF
> +        .e format_boffset       ; SARR ARR IDX STR
> +        swap
> +        popvar $idx             ; SARR ARR STR
> +        rot                     ; ARR STR SARR
> +        sel                     ; ARR STR SARR SLEN
> +        rot                     ; ARR SARR SLEN STR
> +        ains                    ; ARR SARR
> +        swap                    ; SARR ARR
> +        pushvar $idx            ; SARR ARR IDX
> +        push null
> +.l3:
> +        drop
> +        ;; Increase index to process next element.
> +        push ulong<64>1
> +        addlu
> +        nip2                    ; SARR ARR (IDX+1)
> +     .endloop
> +        drop
> +        ;; Honor oacutoff.
> +        pushvar $no_ellip       ; SARR ARR NOELLIP
> +        bnzi .push_ket
> +        drop
> +        push "..."
> +        push ulong<64>0
> +        push ulong<64>3
> +        push "ellipsis"
> +        sprops                  ; SARR ARR ...
> +        rot
> +        sel                     ; ARR ... SARR SLEN
> +        rot                     ; ARR SARR SLEN ...
> +        ains
> +        swap
> +        push null
> +.push_ket:
> +        drop                    ; SARR ARR
> +        swap
> +        sel
> +        push "]"
> +        ains                    ; ARR SARR
> +        ;; Format the array offset if required.
> +        pushoo                  ; ARR SARR OMAPS
> +        bzi .done
> +        drop
> +        sel
> +        push " @ "
> +        ains
> +        swap                    ; SARR ARR
> +        mgeto                   ; SARR ARR BOFF
> +        .e format_boffset       ; SARR ARR STR
> +        rot                     ; ARR STR SARR
> +        sel                     ; ARR STR SARR SLEN
> +        rot                     ; ARR SARR SLEN STR
> +        ains                    ; ARR SARR
> +        push null
> +.done:
> +        ;; We are done.  Cleanup and bye bye.
> +        drop
> +        nip                     ; SARR
> +        sel                     ; SARR SLEN
> +        push ulong<64>0         ; SARR SLEN IDX
> +        swap                    ; SARR IDX SLEN
> +        .call _pkl_reduce_string_array
> +                                ; STR
> +        sel                     ; STR LEN
> +        push ulong<64>0         ; STR LEN IDX
> +        swap                    ; STR IDX LEN
> +        push "array"            ; STR IDX LEN CLASS
> +        sprops                  ; STR
> +        popf 1
> +        return
> +        .end
> +
> +;;; RAS_FUNCTION_STRUCT_FORMATER @struct_type
> +;;; ( SCT DEPTH -- STR )
> +;;;
> +;;; Assemble a function that gets a struct value and a depth
> +;;; level in the stack and push the string representation of
> +;;; the struct to the stack.
> +;;;
> +;;; Macro-arguments:
> +;;; @struct_type
> +;;;   pkl_ast_node with the type fo the struct value to format.
> +
> +        .function struct_formater @struct_type
> +        prolog
> +        pushf 1
> +        regvar $depth           ; SCT
> +        .let #is_union_p = pvm_make_int(PKL_AST_TYPE_S_UNION_P 
> (@struct_type), 32)
> +        ;; Make the string[] which will contain all the formatted struct
> +        mktys                   ; SCT STYP
> +        push null
> +        mktya                   ; SCT ATYP
> +        push ulong<64>0
> +        mka                     ; SCT SARR
> +        swap                    ; SARR SCT
> +        typof                   ; SARR SCT TYP
> +        tysctn                  ; SARR SCT STR
> +        nip
> +        bnn .named_struct
> +        ;; anonymous struct/union
> +        drop
> +        push #is_union_p        ; SARR SCT INT
> +        bnzi .anonymous_union
> +        drop
> +        push "struct"           ; SARR SCT STR
> +        ba .named_struct
> +.anonymous_union:
> +        drop
> +        push "union"
> +.named_struct:
> +        sel
> +        push ulong<64>0
> +        swap
> +        push "struct-type-name" ; SARR SCT STR IDX LEN CLASS
> +        sprops                  ; SARR SCT STR
> +        rot                     ; SCT STR SARR
> +        push ulong<64>0         ; SCT STR SARR IDX
> +        rot                     ; SCT SARR IDX STR
> +        ains
> +        swap                    ; SARR SCT
> +        ;; Stop here if we are past the maximum depth configured in
> +        ;; the VM.
> +        pushod                  ; SARR SCT MDEPTH
> +        bzi .depth_ok
> +        pushvar $depth          ; SARR SCT MDEPTH DEPTH
> +        lei
> +        nip2                    ; SARR SCT (MDEPTH<=DEPTH)
> +        bzi .depth_ok
> +        drop                    ; SARR SCT
> +        push " {...}"
> +        rot                     ; SCT STR SARR
> +        sel                     ; SCT STR SARR IDX
> +        rot                     ; SCT SARR IDX STR
> +        ains                    ; SCT SARR
> +        swap
> +        ba .body_done
> +.depth_ok:
> +        drop                    ; SARR SCT
> +        ;; Iterate on the elements stored in the struct, formating them
> +        ;; in order.
> +        swap                    ; SCT SARR
> +        sel
> +        push " {"
> +        ains                    ; SCT SARR
> +        swap                    ; SARR SCT
> +        .let @field
> + .c      uint64_t i;
> + .c for (i = 0, @field = PKL_AST_TYPE_S_ELEMS (struct_type);
> + .c      @field;
> + .c      @field = PKL_AST_CHAIN (@field))
> + .c   {
> + .c     if (PKL_AST_CODE (@field) != PKL_AST_STRUCT_TYPE_FIELD)
> + .c       continue;
> +        .label .process_struct_field
> +        .label .process_next_alternative
> +        .label .l1
> +        .label .l2
> +        .label .l3
> +        .let #i = pvm_make_ulong (i, 64)
> +        .let @field_name = PKL_AST_STRUCT_TYPE_FIELD_NAME (@field)
> +        .let @field_type = PKL_AST_STRUCT_TYPE_FIELD_TYPE (@field)
> +        ;; Get the value of this field.  If this an union we have to
> +        ;; refer to the field by name, and the first one we found is
> +        ;; the only one.
> +        push #is_union_p
> +        bzi .process_struct_field
> +        ;; union
> +        drop
> +        .let #name_str = pvm_make_string (PKL_AST_IDENTIFIER_POINTER 
> (@field_name))
> +        push #name_str          ; SARR SCT STR
> +        srefnt                  ; SARR SCT STR EVAL
> +        nip                     ; SARR SCT EVAL
> +        bn .process_next_alternative
> +        ba .l2
> +.process_struct_field:
> +        drop
> +        push #i                 ; SARR SCT I
> +        srefi                   ; SARR SCT I EVAL
> +        swap                    ; SARR SCT EVAL I
> +        bzlu .l1
> +        drop
> +        ;; Insert the separator if this is not the first field.
> +        rot                     ; SCT EVAL SARR
> +        sel
> +        push ","
> +        ains                    ; SCT EVAL SARR
> +        ba .l3
> +.l1:
> +        drop
> +.l2:
> +        rot                     ; SCT EVAL SARR
> +.l3:
> +        ;; Indent if in tree-mode.
> +        sel                     ; SCT EVAL SARR IDX
> +        pushvar $depth          ; SCT EVAL SARR IDX DEPTH
> +        push int<32>1
> +        addi
> +        nip2                    ; SCT EVAL SARR IDX (DEPTH+1)
> +        pushoi                  ; SCT EVAL SARR IDX (DEPTH+1) ISTEP
> +        pushom                  ; SCT EVAL SARR IDX DEPTH ISTEP OMODE
> +        .call _pkl_indentation  ; SCT EVAL SARR IDX STR
> +        ains                    ; SCT EVAL SARR
> +        ;; Field name
> + .c   if (@field_name)
> + .c   {
> +        .let #field_name_str = pvm_make_string (PKL_AST_IDENTIFIER_POINTER 
> (@field_name))
> +        sel                     ; SCT EVAL SARR IDX
> +        push #field_name_str
> +        sel
> +        push ulong<64>0
> +        swap
> +        push "struct-field-name"
> +        sprops                  ; SCT EVAL SARR IDX STR
> +        ains                    ; SCT EVAL SARR
> +        sel
> +        push "="
> +        ains                    ; SCT EVAL SARR
> + .c   }
> +        nrot                    ; SARR SCT EVAL
> +        pushvar $depth          ; SARR SCT EVAL DEPTH
> +        push int<32>1
> +        addi
> +        nip2                    ; SARR SCT EVAL (DEPTH+1)
> +        .c PKL_PASS_SUBPASS (@field_type);
> +                                ; SARR SCT STR
> +        rot                     ; SCT STR SARR
> +        sel                     ; SCT STR SARR IDX
> +        rot                     ; SCT SARR IDX STR
> +        ains                    ; SCT SARR
> +        ;; Format the field offset, if required.
> +        .label .no_elem_offset
> +        pushoo                  ; SCT SARR OMAPS
> +        bzi .no_elem_offset
> +        drop                    ; SCT SARR
> +        sel
> +        push " @ "              ; SCT SARR IDX STR
> +        ains
> +        swap                    ; SARR SCT
> +        push #i
> +        srefio
> +        nip                     ; SARR SCT BOFF
> +        .e format_boffset       ; SARR SCT STR
> +        rot                     ; SCT STR SARR
> +        sel
> +        rot                     ; SCT SARR IDX STR
> +        ains
> +        push null               ; SCT SARR NULL
> +.no_elem_offset:
> +        drop
> +        swap                    ; SARR SCT
> +        push #is_union_p
> +        ;; Unions only have one field => we are done.
> +        bnzi .fields_done
> +.process_next_alternative:
> +        drop                    ; SARR SCT
> + .c    i = i + 1;
> + .c }
> +        ba .l4
> +.fields_done:
> +        drop
> +.l4:
> +        ;; Indent if in tree-mode.
> +        pushvar $depth          ; SARR SCT DEPTH
> +        pushoi                  ; SARR SCT DEPTH ISTEP
> +        pushom                  ; SARR SCT DEPTH ISTEP OMODE
> +        .call _pkl_indentation  ; SARR SCT STR
> +        rot                     ; SCT STR SARR
> +        sel                     ; SCT STR SARR IDX
> +        rot                     ; SCT SARR IDX STR
> +        ains
> +        sel
> +        push "}"
> +        ains                    ; SCT SARR
> +        swap
> +.body_done:
> +        ;; Format the struct offset if required.
> +        pushoo                  ; SARR SCT OMAPS
> +        bzi .no_omaps
> +        drop                    ; SARR SCT
> +        mgeto
> +        nip                     ; SARR BOFF
> +        swap                    ; BOFF SARR
> +        sel                     ; BOFF SARR IDX
> +        push " @ "              ; BOFF SARR IDX STR
> +        ains                    ; BOFF SARR
> +        sel                     ; BOFF SARR IDX
> +        rot                     ; SARR IDX BOFF
> +        .e format_boffset       ; SARR IDX STR
> +        ains                    ; SARR
> +        ba .done
> +.no_omaps:
> +        drop2
> +.done:
> +                                ; SARR
> +        sel
> +        push ulong<64>0
> +        swap                    ; SARR IDX LEN
> +        .call _pkl_reduce_string_array
> +                                ; STR
> +        sel
> +        push ulong<64>0
> +        swap                    ; STR IDX LEN
> +        push "struct"
> +        sprops                  ; STR
> +        popf 1
> +        return
> +        .end
> +
>  ;;; RAS_MACRO_PRINT_INT_SUFFIX @type
>  ;;; ( -- )
>  ;;;
> diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
> index 15a5a32a..5c717417 100644
> --- a/libpoke/pkl-insn.def
> +++ b/libpoke/pkl-insn.def
> @@ -60,9 +60,12 @@ PKL_DEF_INSN(PKL_INSN_PUSH,"v","push")
>  PKL_DEF_INSN(PKL_INSN_PUSHR,"r","pushr")
>  PKL_DEF_INSN(PKL_INSN_POPR,"r","popr")
>  PKL_DEF_INSN(PKL_INSN_DROP,"","drop")
> +PKL_DEF_INSN(PKL_INSN_DROP2,"","drop2")
> +PKL_DEF_INSN(PKL_INSN_DROP3,"","drop3")
>  PKL_DEF_INSN(PKL_INSN_SWAP,"","swap")
>  PKL_DEF_INSN(PKL_INSN_NIP,"","nip")
>  PKL_DEF_INSN(PKL_INSN_NIP2,"","nip2")
> +PKL_DEF_INSN(PKL_INSN_NIP3,"","nip3")
>  PKL_DEF_INSN(PKL_INSN_DUP,"","dup")
>  PKL_DEF_INSN(PKL_INSN_OVER,"","over")
>  PKL_DEF_INSN(PKL_INSN_ROT,"","rot")
> @@ -242,6 +245,13 @@ PKL_DEF_INSN(PKL_INSN_SPROPS,"","sprops")
>  PKL_DEF_INSN(PKL_INSN_SPROPH,"","sproph")
>  PKL_DEF_INSN(PKL_INSN_SPROPC,"","spropc")
>  
> +/* Format instructions. */
> +
> +PKL_DEF_INSN(PKL_INSN_FORMATI,"n","formati")
> +PKL_DEF_INSN(PKL_INSN_FORMATIU,"n","formatiu")
> +PKL_DEF_INSN(PKL_INSN_FORMATL,"n","formatl")
> +PKL_DEF_INSN(PKL_INSN_FORMATLU,"n","formatlu")
> +
>  /* Offset instructions.  */
>  
>  PKL_DEF_INSN(PKL_INSN_MKO,"","mko")
> @@ -548,6 +558,10 @@ PKL_DEF_INSN(PKL_INSN_REV,"n","rev")
>  
>  PKL_DEF_INSN(PKL_INSN_PRINT,"a","print")
>  
> +/* Formating macro-instructions.  */
> +
> +PKL_DEF_INSN(PKL_INSN_FORMAT,"a","format")
> +

Please use coherent comments. Either `Format (macro)instructions' or
`Formating (macro)instructions'.

>  /*
>  Local variables:
>  mode:c
> diff --git a/libpoke/pkl-lex.l b/libpoke/pkl-lex.l
> index 55ba36cd..38c3b38d 100644
> --- a/libpoke/pkl-lex.l
> +++ b/libpoke/pkl-lex.l
> @@ -227,6 +227,7 @@ S ::
>  "load"          { return LOAD; }
>  "lambda"        { return LAMBDA; }
>  "assert"        { return ASSERT; }
> +"format"        { return FORMAT; }
>  "__PKL_BUILTIN_RAND__" {
>     if (yyextra->bootstrapped) REJECT; return BUILTIN_RAND; }
>  "__PKL_BUILTIN_GET_ENDIAN__" {
> diff --git a/libpoke/pkl-pass.c b/libpoke/pkl-pass.c
> index 01adbbdd..e17da587 100644
> --- a/libpoke/pkl-pass.c
> +++ b/libpoke/pkl-pass.c
> @@ -566,6 +566,18 @@ pkl_do_pass_1 (pkl_compiler compiler,
>        if (PKL_AST_RAISE_STMT_EXP (node))
>          PKL_PASS (PKL_AST_RAISE_STMT_EXP (node));
>        break;
> +    case PKL_AST_FORMAT_ARG:
> +      if (PKL_AST_FORMAT_ARG_EXP (node))
> +        PKL_PASS (PKL_AST_FORMAT_ARG_EXP (node));
> +      break;
> +    case PKL_AST_FORMAT:
> +      if (PKL_AST_FORMAT_FMT (node))
> +        PKL_PASS (PKL_AST_FORMAT_FMT (node));
> +      if (PKL_AST_FORMAT_TYPES (node))
> +        PKL_PASS_CHAIN (PKL_AST_FORMAT_TYPES (node));
> +      if (PKL_AST_FORMAT_ARGS (node))
> +        PKL_PASS_CHAIN (PKL_AST_FORMAT_ARGS (node));
> +      break;

You don't need to use conditionals for AST children that are not
optional.  This applies to FMT.

>      case PKL_AST_PRINT_STMT_ARG:
>        if (PKL_AST_PRINT_STMT_ARG_EXP (node))
>          PKL_PASS (PKL_AST_PRINT_STMT_ARG_EXP (node));



reply via email to

[Prev in Thread] Current Thread [Next in Thread]