Basic: add step3, vector/hash-map evaluation.
[jackhill/mal.git] / basic / step2_eval.in.bas
index 9a9e48b..3bdcabc 100755 (executable)
@@ -20,7 +20,9 @@ EVAL_AST:
 
   T%=Z%(A%,0)
   IF T%=5 THEN EVAL_AST_SYMBOL
-  IF T%=6 THEN EVAL_AST_LIST
+  IF T%=6 THEN EVAL_AST_SEQ
+  IF T%=8 THEN EVAL_AST_SEQ
+  IF T%=10 THEN EVAL_AST_SEQ
   R%=A%
   GOTO EVAL_AST_RETURN
 
@@ -29,49 +31,64 @@ EVAL_AST:
     IF T3%=0 THEN ER%=1: ER$="'" + ZS$(Z%(A%,1)) + "' not found"
     GOTO EVAL_AST_RETURN
   
-  EVAL_AST_LIST:
-    REM push future return value (new list)
+  EVAL_AST_SEQ:
+    REM push type of sequence
+    ZL%=ZL%+1
+    ZZ%(ZL%)=T%
+    REM push sequence index
+    ZL%=ZL%+1
+    ZZ%(ZL%)=-1
+    REM push future return value (new sequence)
     ZL%=ZL%+1
     ZZ%(ZL%)=ZI%
-    REM push previous new list entry
+    REM push previous new sequence entry
     ZL%=ZL%+1
     ZZ%(ZL%)=ZI%
 
-    EVAL_AST_LIST_LOOP:
-      REM create new list entry
-      Z%(ZI%,0)=6
+    EVAL_AST_SEQ_LOOP:
+      REM create new sequence entry
+      Z%(ZI%,0)=ZZ%(ZL%-3)
       Z%(ZI%,1)=0
       ZI%=ZI%+1
 
-      REM check if we are done evaluating the list
-      IF Z%(A%,1)=0 THEN GOTO EVAL_AST_LIST_LOOP_DONE
+      REM update index
+      ZZ%(ZL%-2)=ZZ%(ZL%-2)+1
+
+      REM check if we are done evaluating the sequence
+      IF Z%(A%,1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
 
       REM create value ptr placeholder
       Z%(ZI%,0)=15
       Z%(ZI%,1)=0
       ZI%=ZI%+1
 
+      REM if hashmap, skip eval of even entries (keys)
+      R%=A%+1
+      IF (ZZ%(ZL%-3)=10) AND ((ZZ%(ZL%-2) AND 1)=0) THEN GOTO EVAL_AST_SEQ_SKIP
+
       REM call EVAL for each entry
       A%=A%+1: GOSUB EVAL
       A%=A%-1
 
-      REM update previous list entry to point to current entry
+      EVAL_AST_SEQ_SKIP:
+
+      REM update previous sequence entry to point to current entry
       Z%(ZZ%(ZL%),1)=ZI%
       REM update previous value pointer to evaluated entry
       Z%(ZZ%(ZL%)+1,1)=R%
       REM update previous ptr to current entry
       ZZ%(ZL%)=ZI%
 
-      REM process the next list entry
+      REM process the next sequence entry
       A%=Z%(A%,1)
 
-      GOTO EVAL_AST_LIST_LOOP
-    EVAL_AST_LIST_LOOP_DONE:
-      REM pop previous new list entry value
+      GOTO EVAL_AST_SEQ_LOOP
+    EVAL_AST_SEQ_LOOP_DONE:
+      REM pop previous new sequence entry value
       ZL%=ZL%-1
-      REM pop return value (new list)
+      REM pop return value (new seq), index, and seq type
       R%=ZZ%(ZL%)
-      ZL%=ZL%-1
+      ZL%=ZL%-3
       GOTO EVAL_AST_RETURN
 
   EVAL_AST_RETURN:
@@ -96,16 +113,16 @@ EVAL:
     GOSUB EMPTY_Q
     IF R% THEN R%=A%: GOTO EVAL_RETURN
 
-    GOSUB EVAL_AST
-    IF ER%=1 THEN GOTO EVAL_RETURN
-    F%=R%+1
-    AR%=Z%(R%,1): REM REST
-    R%=F%: GOSUB DEREF
-    F%=R%
-    IF Z%(F%,0)<>12 THEN ER%=1: ER$="apply of non-function": GOTO EVAL_RETURN
-    GOSUB DO_FUNCTION
-
-    GOTO EVAL_RETURN
+    EVAL_INVOKE:
+      GOSUB EVAL_AST
+      IF ER%=1 THEN GOTO EVAL_RETURN
+      F%=R%+1
+      AR%=Z%(R%,1): REM REST
+      R%=F%: GOSUB DEREF
+      F%=R%
+      IF Z%(F%,0)<>12 THEN ER%=1: ER$="apply of non-function": GOTO EVAL_RETURN
+      GOSUB DO_FUNCTION
+      GOTO EVAL_RETURN
 
   EVAL_RETURN:
     E%=ZZ%(ZL%-1): A%=ZZ%(ZL%): ZL%=ZL%-2
@@ -221,6 +238,6 @@ MAIN:
       GOTO MAIN_LOOP
 
   MAIN_DONE:
-    PRINT "Free: " + STR$(FRE(0)): REM abc
+    PRINT "Free: " + STR$(FRE(0))
     END