Skip to content

Instantly share code, notes, and snippets.

@paniq paniq/conspire2.scm Secret
Last active Aug 29, 2015

What would you like to do?
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:
; 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>)
; 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
; 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
(var mustard? false)
; maps a collection of names to the local scope
; this can also be used as an enumerator
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
; ++ 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. "" will be evaluated before "" 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.
; 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.