# HG changeset patch # User naryl # Date 2020-08-25 17:32:38 # Node ID 44143cfd92083785932def03d47d95ef5fba4301 # Parent 9d6b47b82870d28c13c78c30c96e4e811734ec9d Fix two regressions diff --git a/src/api.ps b/src/api.ps --- a/src/api.ps +++ b/src/api.ps @@ -68,6 +68,9 @@ (@ event page-y))) (finish-menu nil)))) +(defun init-globals (game-name) + (chain *object (assign *globals (getprop *default-globals game-name)))) + (defun call-serv-loc (var-name &rest args) (let ((loc-name (get-global var-name 0))) (when loc-name @@ -128,11 +131,14 @@ ;;; Function calls (defun init-args (args) - (dotimes (i (length args)) - (let ((arg (elt args i))) - (if (numberp arg) - (set-var args i :num arg) - (set-var args i :str arg))))) + (dotimes (i 10) + (set-global "ARGS" i 0) + (set-global "$ARGS" i "") + (when (< i (length args)) + (let ((arg (elt args i))) + (if (numberp arg) + (set-global "ARGS" i arg) + (set-global "$ARGS" i arg)))))) (defun get-result () (or (get-global "$RESULT" 0) @@ -250,14 +256,21 @@ (elt slot index) (elt slot (getprop slot :indexes index)))) +(defun set-global (name index value) + (set-any-element (getprop *globals name) index value)) + (defun get-global (name index) - (elt (getprop *globals name) index)) + (get-element (getprop *globals name) index)) -(defun kill-var (store name &optional index) - (setf name (chain name (to-upper-case))) - (if (and index (not (= 0 index))) - (chain (getprop *globals name) (kill index)) - (delete (getprop *globals name))) +(defun kill-var (&optional name index) + (cond (name + (setf name (chain name (to-upper-case))) + (if (and index (not (= 0 index))) + (chain (getprop *globals name) (kill index)) + (delete (getprop *globals name)))) + (t + (setf *globals (create)) + (init-globals *main-game))) (void)) (defun array-size (name) diff --git a/src/intrinsic-macros.lisp b/src/intrinsic-macros.lisp --- a/src/intrinsic-macros.lisp +++ b/src/intrinsic-macros.lisp @@ -8,11 +8,13 @@ ;;; 2var -(defpsmacro killvar (varname &optional index) +(defpsmacro killvar (&optional varname index) `(api-call kill-var ,varname ,index)) (defpsmacro killall () - `(api-call kill-all)) + `(progn + (killvar) + (killobj))) ;;; 3expr @@ -84,6 +86,21 @@ ;;; 10dynamic +(defpsmacro dynamic (block &rest args) + `(progn + (when (stringp ,block) + (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC.")) + (api:with-call-args ,args + (funcall ,block)) + (void))) + +(defpsmacro dyneval (block &rest args) + `(progn + (when (stringp block) + (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL.")) + (api:with-call-args args + (funcall block)))) + ;;; 11main (defpsmacro desc (s) diff --git a/src/intrinsics.ps b/src/intrinsics.ps --- a/src/intrinsics.ps +++ b/src/intrinsics.ps @@ -116,19 +116,6 @@ ;;; 10dynamic -(defun dynamic (block &rest args) - (when (stringp block) - (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC.")) - (api:with-call-args args - (funcall block args)) - (void)) - -(defun dyneval (block &rest args) - (when (stringp block) - (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL.")) - (api:with-call-args args - (funcall block args))) - ;;; 11main (defun main-p (s) @@ -219,7 +206,7 @@ (void)) (defun killobj (&optional (num nil)) - (if (eq nil num) + (if (eq undefined num) (setf *objs (create)) (delobj (elt (chain *object (keys *objs)) num))) (api:update-objs) diff --git a/src/main.ps b/src/main.ps --- a/src/main.ps +++ b/src/main.ps @@ -4,6 +4,7 @@ ;;; Game session state (saved in savegames) ;; Variables (var *globals (create)) +(var *default-globals (create)) ;; Inventory (objects) (var *objs (create)) (var *current-location nil) @@ -46,8 +47,9 @@ (#.(intern "SET-TIMER" "TXT2WEB.API") *timer-interval) ;; Start the first game - (#.(intern "RUN-GAME" "TXT2WEB.API") - (chain *object (keys *games) 0)) + (let ((first-game (chain *object (keys *games) 0))) + (#.(intern "INIT-GLOBALS" "TXT2WEB.API") first-game) + (#.(intern "RUN-GAME" "TXT2WEB.API") first-game)) (values)) ;;; Some very common utilities (for both api and lib) diff --git a/src/package.lisp b/src/package.lisp --- a/src/package.lisp +++ b/src/package.lisp @@ -8,7 +8,7 @@ (:export #:api-call #:by-id #:has - #:*globals #:*objs #:*current-location + #:*globals #:*default-globals #:*objs #:*current-location #:*started-at #:*timer-interval #:*timer-obj #:*loaded-games #:*acts #:*state-stash #:*playing #:*locals @@ -32,7 +32,7 @@ #:report-error #:sleep #:init-dom #:call-serv-loc #:*serv-vars* #:newline #:clear-id #:prepare-contents #:get-id #:set-id #:append-id - #:init-args #:get-result #:call-loc #:call-act + #:get-result #:call-loc #:call-act #:get-frame #:add-text #:get-text #:clear-text #:enable-frame #:add-act #:del-act #:clear-act #:update-acts #:set-str-element #:set-any-element #:set-serv-var @@ -45,6 +45,7 @@ #:clean-audio #:show-image #:opengame #:savegame + #:init-globals )) ;;; QSP library functions and macros diff --git a/src/parser.lisp b/src/parser.lisp --- a/src/parser.lisp +++ b/src/parser.lisp @@ -181,7 +181,7 @@ (p:parse 'expression (p:text (mapcar 'second (second list))))) (defun parse-exec (list) - (list* 'lib:exec (p:parse 'exec-body (p:text (second list))))) + (list* 'lib:exec (p:parse 'exec-body (p:text (mapcar #'second (second list)))))) (p:defrule sstring-interpol (and "<<" (+ (and (p:! ">>") sstring-char)) @@ -592,11 +592,16 @@ (p:defrule and-expr (and eq-expr (* (and spaces? and-op spaces? eq-expr))) (:function do-binop)) -(p:defrule eq-expr (and sum-expr (* (and spaces? (or "<=" ">=" "=<" "=>" "<>" - "=" "<" ">") +(p:defrule eq-expr (and sum-expr (* (and spaces? comp-op spaces? sum-expr))) (:function do-binop)) +(p:defrule comp-op (or "<=" ">=" "=<" "=>" "<>" "=" "<" ">") + (:lambda (op) + (cond ((string= op "=>") ">=") + ((string= op "=<") "<=") + (t op)))) + (p:defrule sum-expr (and mod-expr (* (and spaces? (or #\+ #\-) spaces? mod-expr))) (:function do-binop)) diff --git a/src/ps-macros.lisp b/src/ps-macros.lisp --- a/src/ps-macros.lisp +++ b/src/ps-macros.lisp @@ -49,6 +49,8 @@ (defparameter *special-variables* '((usehtml 0) + (args 0) + ($args 0) (result 0) ($result 0) ($ongload 0) @@ -70,7 +72,8 @@ (setf (@ *games ,name) (create)) ;; Global variables from this game - (create-globals ,*globals*) + (setf (@ *default-globals ,name) + (create-globals ,*globals*)) ;; Locations ,@(loop :for location :in body :collect `(setf (@ *games ,name ,(caadr location)) @@ -83,12 +86,12 @@ (defpsmacro goto% (target &rest args) `(progn - (goto ,target ,args) + (goto ,target ,@args) (exit))) (defpsmacro xgoto% (target &rest args) `(progn - (xgoto ,target ,args) + (xgoto ,target ,@args) (exit))) ;;; 2var @@ -105,14 +108,12 @@ :key #'first :test-not #'eq)))))) (let ((names (remove-duplicates (mapcar #'first globals)))) - `(chain *object - (assign *globals - (create - ,@(loop :for sym :in names - :for indexes := (indexes sym) - :for name := (string-upcase sym) - :append `(,name - (api-call new-var ,name ,@indexes))))))))) + `(create + ,@(loop :for sym :in names + :for indexes := (indexes sym) + :for name := (string-upcase sym) + :append `(,name + (api-call new-var ,name ,@indexes))))))) (walker:deftransform globals qspvar (&rest var) (pushnew var *globals* :test #'equal) @@ -220,6 +221,11 @@ (walker:deftransform apply-vars qspfor (var from to step body) (list* 'qspfor var (mapcar #'walker:walk-continue (list from to step body)))) +(defpsmacro get-slot (name) + `(getprop + (if (chain locals (includes name)) locals *globals) + (string-upcase name))) + ;;; 3expr (defpsmacro <> (op1 op2) diff --git a/tests/regression-1.qsps b/tests/regression-1.qsps new file mode 100644 --- /dev/null +++ b/tests/regression-1.qsps @@ -0,0 +1,8 @@ +# begin + x = -1 + gt 'loc', x +- +# loc + if args[0]: 'args[0] = -1' + 'end' +- diff --git a/tests/regression-2.qsps b/tests/regression-2.qsps new file mode 100644 --- /dev/null +++ b/tests/regression-2.qsps @@ -0,0 +1,19 @@ +# begin + func('getObjByKey', 'item') +- + +# getObjByKey + $needle = $args[0] + i = 1 + :lab + if i <= countobj: + if $getobj(i) = $needle: + result = i + exit + else + i += 1 + jump 'lab' + end + end + result = -1 +-