Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

82 struct #93

Merged
merged 12 commits into from
Nov 13, 2022
Merged

82 struct #93

merged 12 commits into from
Nov 13, 2022

Conversation

skx
Copy link
Owner

@skx skx commented Nov 12, 2022

This pull-request contains a "struct" implementation, which currently allows structures to be defined - as a list of fields, and objects created assuming all fields are present. One a struct has been created magical methods allow type-checking and field access/updates.

This will close #82, once complete.

Sample usage, which works with this pull-request:

;; define a structure
(struct person name address)
(struct cat    name age)

;; create an instance of a person
(set! self (person "Steve Kemp" "My home address, Helsinki, Finland"))

;; create an instance of a cat
(set! kitty (cat "Meow" (- 2022 2018 )))

;; show the type of our object, and the fields
(print "The person struct.type is %s" (type self))
(print "The person struct.address contains:%s" (get self "address"))
(print "The person struct.name contains:%s" (get self "name"))

;; Type-checking should "just work"
(if (person? self)
    (print "self is a person")
  (print "self is NOT a person - bug"))

(if (cat? self)
    (print "A person cannot be a cat - bug"))

(if (cat? kitty)
    (print "We have a cat, aged %d" (get kitty "age")))

(print (cat.name kitty))
(cat.name kitty (join (list "My " "New" " " "Name")))
(print (cat.name kitty))

Here you'll notice that the struct is actually a hash, and we're merely setting the named fields as key/val pairs.

This is pretty smart, all we've really done is recorded the fields a structure should contain, and hooked into our execution to instantiate a new hash when we see a named structure - before falling back to invoking a command instead.

The bit that's missing?

  • We want to allow structs to be defined.
  • We want to allow structs to be instantiated.
  • We want to have "type?" support.
  • We want to have field-accessors created.
  • We want to have field-mutators created.
  • Test cases.
  • Documentation.

Adding accessors was a little tricky, but we store the name of the faux method in a map with the appropriate field as the value. This allows accesses to be found and updates to be made.

The biggest issue here is that we're doing extra checks on the "hot path", so the whole eval method is getting deeply complex and slower. I think that needs to be spun out into a different issue.

skx added 10 commits November 12, 2022 16:44
This pull-request contains a proof of concept "struct" implementation,
which currently allows structures to be defined - as a list of fields,
and objects created assuming all fields are present.

This will close #82, once complete.

Sample usage:

      ;; define a structure
      (struct person name address)

      ;; create an instance
      (set! self (person "Steve Kemp" "My home address, Helsinki, Finland"))

      (print "struct.type is %s" (type self))
      (print "struct.address contains:%s" (get self "address"))
      (print "struct.name contains:%s" (get self "name"))

Here you'll notice that the struct is actually a hash, and we're
merely setting the named fields as key/val pairs.

This is pretty smart, all we've really done is recorded the fields
a structure should contain, and hooked into our execution to
instantiate a new hash when we see a named structure - before falling
back to invoking a command instead.

The bit that's missing?  We want to have "type?" support, and we
want to have accessors created.

type? support is trivial if we copy/paste primitive.Hash into
primitive.Struct and add a "type" member.  We just return:

      struct-%s, primitive.Type

However adding accessors get's tricky.  I could have another map
but getting type validaiton is gonna be a pain.  It also seems like
if I continue to abuse/reuse the Hash type we could use something
siumilar to allow:

        hash.field

To either get/set values and that feels like a useful piece of
syntatic sugar.  Will experiment before committing.
@skx skx mentioned this pull request Nov 13, 2022
@skx skx merged commit ebd8879 into master Nov 13, 2022
@skx skx deleted the 82-struct branch November 13, 2022 12:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Look at "structure"
1 participant