Browse Source

Added current state section, state var macro

State variables do not yet work because a system is needed to handle
late registration of them as state variables.
HotReloadingState
Macoy Madson 1 month ago
parent
commit
79c0cb5c50
3 changed files with 73 additions and 25 deletions
  1. +11
    -0
      ReadMe.org
  2. +57
    -18
      runtime/HotReloading.cake
  3. +5
    -7
      runtime/TextAdventure.cake

+ 11
- 0
ReadMe.org View File

@@ -18,6 +18,17 @@ It is a transpiler which generates C/C++ from a Lisp dialect.
- Output is human-readable C/C++ source and header files. This is so if I decide it was unsuccessful, or only useful in some scenarios (e.g. generating serialization wrappers), I can still use the output code from hand-written C/C++ code

Many of these come naturally from using C as the backend. Eventually it would be cool to not have to generate C (e.g. generate LLVM bytecode instead), but that can a project for another time.
* Current state
/(updated as of 2020-10-06)/

Cakelisp is largely working. At this point, I need to write a real program in Cakelisp in order to inform what features are missing and what changes to existing features need to be made. This will ensure I work on features which really matter when building actual applications.

The following features are as of yet unimplemented:
- Mapping files
- Pure C output
- Building and running the compiler on Windows

Hot reloading is partially implemented, but will need some further iteration.
* Building Cakelisp itself
Install [[https://www.perforce.com/documentation/jam-documentation][Jam]]:
#+BEGIN_SRC sh


+ 57
- 18
runtime/HotReloading.cake View File

@@ -113,6 +113,10 @@
(return true))

(defmacro hot-reload-make-state-variable-initializer ()
;; Code that isn't hot-reloaded should be compatible if we do nothing
(unless (field environment enableHotReloading)
(return true))

(state-variable-initializer-preamble)

(tokenize-push
@@ -163,24 +167,59 @@
1))
(set (field array-length-token contents) (call (in std to_string) array-length))

;; Regardless of enableHotReloading, make array length available so that non-hot-reloaded code
;; still works when asking for the length
(tokenize-push
output
(var-noreload (token-splice-ref array-length-name) (const int) (token-splice-ref array-length-token))
(defun-local (token-splice-ref init-function-name) ()
(var existing-value (* void) nullptr)
(if (hot-reload-find-variable (token-splice-ref string-var-name) (addr existing-value))
(set (no-eval-var (token-splice-ref name)) (type-cast existing-value (* (token-splice-ref type-strip-array))))
(block
;; C can have an easier time with plain old malloc and cast
(set (no-eval-var (token-splice-ref name)) (new-array (token-splice-ref array-length-name)
(token-splice-ref type-strip-array)))
(var static-intializer-full-array (const (token-splice-ref type)) (token-splice-ref assignment))
;; Have to handle array initialization ourselves, because the state variable is just a pointer now
(var current-elem int 0)
(while (< current-elem (token-splice-ref array-length-name))
(set (at current-elem (no-eval-var (token-splice-ref name)))
(at current-elem static-intializer-full-array))
(incr current-elem))
(hot-reload-register-variable (token-splice-ref string-var-name)
(no-eval-var (token-splice-ref name)))))))
(var-noreload (token-splice-ref array-length-name) (const int) (token-splice-ref array-length-token)))

(when (field environment enableHotReloading)
(tokenize-push
output
(defun-local (token-splice-ref init-function-name) ()
(var existing-value (* void) nullptr)
(if (hot-reload-find-variable (token-splice-ref string-var-name) (addr existing-value))
(set (no-eval-var (token-splice-ref name)) (type-cast existing-value (* (token-splice-ref type-strip-array))))
(block
;; C can have an easier time with plain old malloc and cast
(set (no-eval-var (token-splice-ref name)) (new-array (token-splice-ref array-length-name)
(token-splice-ref type-strip-array)))
(var static-intializer-full-array (const (token-splice-ref type)) (token-splice-ref assignment))
;; Have to handle array initialization ourselves, because the state variable is just a pointer now
(var current-elem int 0)
(while (< current-elem (token-splice-ref array-length-name))
(set (at current-elem (no-eval-var (token-splice-ref name)))
(at current-elem static-intializer-full-array))
(incr current-elem))
(hot-reload-register-variable (token-splice-ref string-var-name)
(no-eval-var (token-splice-ref name))))))))
(return true))

;; TODO: LEFT OFF: Why does this break the var->pointer auto deref? Does it happen too late? If so,
;; I must add symbol-level dependency resolution to fix
(defmacro state-var ()
(destructure-arguments name-index type-index assignment-index)
(quick-token-at name name-index)
(quick-token-at type type-index)
(quick-token-at assignment assignment-index)
(tokenize-push
output
(var (token-splice-ref name) (token-splice-ref type) (token-splice-ref assignment)))
(when (field environment enableHotReloading)
(tokenize-push
output
(hot-reload-make-state-variable-initializer (token-splice-ref name) (token-splice-ref type)
(token-splice-ref assignment))))
(return true))

;; TODO: Add type manipulations for array version
;; (defmacro state-var-array ()
;; (destructure-arguments name-index type-index assignment-index)
;; (quick-token-at name name-index)
;; (quick-token-at type type-index)
;; (quick-token-at assignment assignment-index)
;; (tokenize-push
;; (var (token-splice-ref name) (token-splice-ref type) (token-splice-ref assignment))
;; (hot-reload-make-state-variable-initializer (token-splice-ref name) (token-splice-ref type)
;; (token-splice-ref assignment)))
;; (return true))

+ 5
- 7
runtime/TextAdventure.cake View File

@@ -26,20 +26,20 @@
"inside home" "Surprise! Your home is filled with cake. You look at your hands. You are cake."
(array))))))

(var rooms-state (* room) nullptr)
;; TODO: Make arrays also be var, but have generator not cause auto derefs, just change [] to *
(var-noreload rooms-state (* room) nullptr)
(hot-reload-make-state-variable-array-initializer rooms-state ([] room) (array
(array "front porch" "You're outside the front door of your home. The lights are off inside."
(array (array
"inside home" "Surprise! Your home is filled with cake. You look at your hands. You are cake."
(array))))))

(var num-times-hot-reloaded int 0)
(hot-reload-make-state-variable-initializer num-times-hot-reloaded int 0)
(state-var num-times-hot-reloaded int 0)

;; This now makes order matter, because if we move it up we'll get a null pointer exception
(var current-room (* (const room)) (addr (at 0 rooms-state)))
(hot-reload-make-state-variable-initializer current-room (* (const room)) (addr (at 0 rooms-state)))
(state-var current-room (* (const room)) (addr (at 0 rooms-state)))

;; TODO: This should be autogenerated
(defun libGeneratedCakelisp_initialize ()
(num-times-hot-reloaded-initialize)
(rooms-state-initialize)
@@ -74,8 +74,6 @@
(printf "Num times reloaded: %d\n" num-times-hot-reloaded)
(++ num-times-hot-reloaded)

(printf "Num intro rooms: %d\n" (sizeof rooms-state))

(print-room current-room)

(var input char 0)


Loading…
Cancel
Save