toctave

t(iny)octave
git clone https://0xff.ir/g/toctave.git
Log | Files | Refs | README

toctave.jitter (4762B)


      1 # toctave VM specification
      2 
      3 # Copyright (C) 2020-2021, Mohammad-Reza Nabipoor
      4 # SPDX-License-Identifier: GPL-3.0-or-later
      5 
      6 vm
      7   set prefix "toctave"
      8 end
      9 
     10 stack s
     11   long-name "mainstack"
     12   c-element-type "double"
     13   c-initial-value "0.0"
     14   element-no 4096
     15   guard-underflow
     16   guard-overflow
     17   tos-optimized
     18 end
     19 
     20 wrapped-functions
     21   pow
     22   toctave_var
     23   toctave_var_set
     24 end
     25 
     26 state-struct-runtime-c
     27   code
     28     double result;
     29 
     30     jitter_program_point point;
     31     int status;
     32     void* env;
     33   end
     34 end
     35 
     36 state-initialization-c
     37   code
     38     jitter_state_runtime->result = 0.0 / 0.0; // NaN
     39     jitter_state_runtime->point = NULL;
     40     jitter_state_runtime->status = -1;
     41   end
     42 end
     43 
     44 early-header-c
     45   code
     46 #include <math.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <stdint.h>
     50 
     51 _Bool toctave_var(void* env, const char* name, double* val);
     52 void toctave_var_set(void* env, const char* name, double val);
     53 
     54 union double_uint64
     55 {
     56   double d;
     57   uint64_t u64;
     58 };
     59 
     60 #define TOCTAVE_STATUS_DONE 0
     61 #define TOCTAVE_STATUS_YIELD 1
     62   end
     63 end
     64 
     65 initial-vm1-c
     66   code
     67 #define nan_unbox_uint(p) (((p) & /*mask*/(((uint64_t)1 << 51) - 1)) << 3)
     68 #define nan_unbox(dbl) nan_unbox_uint(((union double_uint64){ .d = (dbl) }).u64)
     69   end
     70 end
     71 
     72 initial-vm2-c
     73   code
     74 #define nan_unbox_uint(p) (((p) & /*mask*/(((uint64_t)1 << 51) - 1)) << 3)
     75 #define nan_unbox(dbl) nan_unbox_uint(((union double_uint64){ .d = (dbl) }).u64)
     76   end
     77 end
     78 
     79 printer-c
     80   code
     81 
     82 // Jitter uses this function to print literal values in instructions (like
     83 // push instruction)
     84 static void
     85 double_literal_printer(jitter_print_context ctx, uintptr_t n)
     86 {
     87   union double_uint64 x;
     88 
     89   x.u64 = n;
     90   jitter_print_double(ctx, x.d);
     91 }
     92 
     93 static void
     94 var_literal_printer(jitter_print_context ctx, uintptr_t n)
     95 {
     96   union double_uint64 x;
     97 
     98   x.u64 = n;
     99   n = nan_unbox(x.d); // reusing `n`
    100   jitter_print_char_star(ctx, (const char*)n);
    101 }
    102 
    103   end
    104 end
    105 
    106 # Stack manipulation
    107 
    108 # Push a double on the stack
    109 # Stack: ( -- a)
    110 instruction push (?n double_literal_printer)
    111   code
    112     union double_uint64 x;
    113 
    114     x.u64 = JITTER_ARGN0;
    115     TOCTAVE_PUSH_MAINSTACK(x.d);
    116   end
    117 end
    118 
    119 # Pop the value on stack and save it into `result` field
    120 # Stack: (a -- )
    121 instruction pop ()
    122   code
    123     TOCTAVE_STATE_RUNTIME_FIELD(result) = TOCTAVE_TOP_MAINSTACK();
    124     TOCTAVE_DROP_MAINSTACK();
    125   end
    126 end
    127 
    128 # Drop the value on stack
    129 # Stack: (a -- )
    130 instruction drop ()
    131   code
    132     TOCTAVE_DROP_MAINSTACK();
    133   end
    134 end
    135 
    136 # Push the value of variable onto the stack
    137 # Stack: ( -- a)
    138 instruction pushvar (?n var_literal_printer) # , ?f)
    139   code
    140     const char* name = (const char*)nan_unbox_uint(JITTER_ARGN0);
    141     // For simplicity, we assume the variable is defined
    142     double d;
    143     _Bool found = toctave_var(TOCTAVE_STATE_RUNTIME_FIELD(env), name, &d);
    144 
    145     // JITTER_BRANCH_FAST_IF_NONZERO(found, JITTER_ARGF1);
    146     if (!found)
    147       d = 0.0 / 0.0; // Put a NaN there
    148     TOCTAVE_PUSH_MAINSTACK(d);
    149   end
    150 end
    151 
    152 # Pop the value on the stack and save it into variable
    153 # Stack: (a -- )
    154 instruction popvar (?n var_literal_printer)
    155   code
    156     const char* name = (const char*)nan_unbox_uint(JITTER_ARGN0);
    157 
    158     toctave_var_set(
    159       TOCTAVE_STATE_RUNTIME_FIELD(env), name, TOCTAVE_TOP_MAINSTACK());
    160     TOCTAVE_DROP_MAINSTACK();
    161   end
    162 end
    163 
    164 instruction pushnan ()
    165   code
    166     TOCTAVE_PUSH_MAINSTACK(0.0 / 0.0);
    167   end
    168 end
    169 
    170 # Arithmetic
    171 
    172 # Stack: (a b -- a^b)
    173 instruction pow ()
    174   code
    175     TOCTAVE_TOP_MAINSTACK() =
    176       pow(/* a */ TOCTAVE_UNDER_TOP_MAINSTACK(),
    177           /* b */ TOCTAVE_TOP_MAINSTACK()); /* Stack: (a a^b) */
    178     TOCTAVE_NIP_MAINSTACK();                /* Stack: (a^b) */
    179   end
    180 end
    181 
    182 # Stack: (a b -- a*b)
    183 instruction mul ()
    184   code
    185     TOCTAVE_TOP_MAINSTACK() =
    186       /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() *
    187       /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */
    188     TOCTAVE_NIP_MAINSTACK();           /* Stack: (a*b) */
    189   end
    190 end
    191 
    192 # Stack: (a b -- a/b)
    193 instruction div ()
    194   non-relocatable
    195   code
    196     TOCTAVE_TOP_MAINSTACK() =
    197       /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() /
    198       /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */
    199   end
    200 end
    201 
    202 # Stack: (a b -- a+b)
    203 instruction add ()
    204   code
    205     TOCTAVE_TOP_MAINSTACK() =
    206       /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() +
    207       /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */
    208   end
    209 end
    210 
    211 # Stack: (a b -- a-b)
    212 instruction sub ()
    213   code
    214     TOCTAVE_TOP_MAINSTACK() =
    215       /* a */ TOCTAVE_UNDER_TOP_MAINSTACK() -
    216       /* b */ TOCTAVE_TOP_MAINSTACK(); /* Stack: (a a*b) */
    217   end
    218 end
    219 
    220 # Control Flow
    221 
    222 instruction yield (?l)
    223   code
    224     TOCTAVE_STATE_RUNTIME_FIELD(point) = JITTER_ARGP0;
    225     TOCTAVE_STATE_RUNTIME_FIELD(status) = TOCTAVE_STATUS_YIELD;
    226   end
    227 end
    228 
    229 instruction done ()
    230   code
    231     TOCTAVE_STATE_RUNTIME_FIELD(point) = NULL;
    232     TOCTAVE_STATE_RUNTIME_FIELD(status) = TOCTAVE_STATUS_DONE;
    233   end
    234 end