Skip to content

Instantly share code, notes, and snippets.

@paniq
Last active August 29, 2015 14:23
Show Gist options
  • Save paniq/34525b55cd4ae8744961 to your computer and use it in GitHub Desktop.
Save paniq/34525b55cd4ae8744961 to your computer and use it in GitHub Desktop.
next conspire features
; the special forms of conspire2:
; (__quote <expr>)
; (__if <expr> <true expr> <false expr>)
; (__for (<var> <start> <stop>) <expr> ...)
; (__var <var> <expr>)
; (__scope)
; (__function (<arg> ...) <expr> ...)
; (__meta-eval <expr>)
; (__do <expr> ...)
; builtin variables:
; NULL
; nil
; true
; false
; module-path
; meta-env
; builtin functions:
; (symbol <name>)
; (table-apply <function> <table>)
; (table-call <function> <arg> ...)
; (table-get <table> <key>)
; (table-set <table> <key> <expr>)
(conspire2
; scopes
; ------
; the 'let' and 'letrec' keywords are no longer in use; instead, new scopes
; (which are analog to self-executing anonymous functions) use a 'do' keyword;
; the last expression in a scope is returned.
(print (do
; adds two numbers but has no visible effect
(+ 10 20)
; is executed immediately; scopes can be nested
(do (print "hello world"))
; returns 5 and causes "5" to be printed to the screen
5
))
; defining values
; ---------------
; the 'define' keyword does no longer exist; instead, variables and functions are declared
; with their own respective keywords
; maps the name "foo" to the value 10 in the local scope
(var foo 10)
; binds the name "foo" to an undefined value in the local scope
(var foo2)
; maps the name "mustard?" to the value false in an anonymous scope
(do
(var mustard? false)
)
; maps a collection of names to the local scope
; this can also be used as an enumerator
(var
ham 5
eggs 10
spam ++ ; spam is mapped to 11
eggsnspam (+ eggs spam) ; eggsnspam is mapped to 21
lettuce () ; lettuce is declared without a bound value
)
; maps the name "bar" to a function taking two arguments in the local scope
(function bar (x y)
(+ x y)
)
; anonymous (lambda) functions
; ----------------------------
; lambda functions now use the same syntax as defined functions, with the name left out
; assigns an anonymous function to the scope variable "bar"
; equivalent to the declaration of bar above
(var bar (function (x y)
(+ x y)
))
; syntax scope
; ------------
; declaring new syntax handlers has an immediate effect during parsing, but syntax
; is no longer declared globally, but only available to the scope within which it has
; been declared; syntax declared at module level can be imported from other modules.
; file1.csp
(do
; ++ syntax only available in this scope
(syntax ++ (function (o) (backquote (+ (unquote (: o 2)) 1))))
; will print 21
(print (++ 20))
)
; will cause an error
(print (++ 20))
; ++ syntax declared top level, available for the whole module
(syntax ++ (function (o) (backquote (+ (unquote (: o 2)) 1))))
; will print 21
(print (++ 20))
; file2.csp
; requiring a module file does not import its syntax
(csp-require "file1")
; will cause an error
(print (++ 20))
; translate file1 without executing the main unit and import ++ into the
; module syntax namespace
(syntax-import "file1" ++)
; will now work as expected
(print (++ 20))
; symbol prefix syntax
; --------------------
; syntax handlers can be defined for prefixes of symbols to implement
; special accessors or numerical notations; the longest prefix matches
; first, so e.g. "...foo" will be evaluated before "..foo" and ".foo"
; maps the prefix "." to a handler function that replaces
; e.g. (print .a.b.c) with (print (getkey a "b" "c"))
; a standalone "." will not be matched.
(syntax-prefix . (function (o)
(var items (split o "."))
(backquote (getkey
(unquote (: items 1))
(unquote-splice (each x (list-slice items 2) (ast-tostring x)))
))
))
; infix operator syntax
; ---------------------
; syntax handlers can be defined for infix operators to implement
; more natural "mathematical" operators; infix operators only match
; to list elements in the order a <operator> b and typically
; transform them into (<operator> a b); If the list containing
; the infix operator has only three elements, it is completely replaced.
; infix syntax only matches after list prefix syntax.
; precedence and fixity must be specified with two initial arguments,
; a precedence priority from 0 to n (0 being the highest), and either
; > or < to specify left-to-right or right-to-left associativity.
; converts the -> infix operator into an anonymous function declaration,
; so (a b) -> (+ a b) turns into (function (a b) (+ a b))
(syntax-infix 0 > -> (function (o)
(backquote (function (unquote (: o 1))
(unquote-splice (list-slice o 2))
))
))
; scope tables
; ------------
; each scope in the runtime is a table (locals)
; defining a new object (function, global variable, etc.) adds the object to the scope table
; the scope table uses the enveloping scope as metatable
; so a lookup iterates from the current table through the parent tables
; it is possible to return and manually edit the scope table
(function (test1 a b c)
(var d 50)
; returns the scope table {a=a,b=b,c=c,d=50}, with the environment
; as metatable - this is the functions actual scope table and can
; be altered.
(locals)
)
; or selectively return certain variables inside a scope table, allowing
; to rename some of the variables on the fly;
(function (test2 a b c)
; returns a new table {a=a,x=b}, without a metatable; editing this
; table will have no effect.
(locals a (x b))
)
; and likewise, the module can export its entire local scope that way
(locals)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment