algebrite
Version:
Computer Algebra System in Coffeescript
81 lines (66 loc) • 2.1 kB
text/coffeescript
# Store a function definition
#
# Example:
#
# f(x,y)=x^y
#
# For this definition, p1 points to the following structure.
#
# p1
# |
# ___v__ ______ ______
# |CONS |->|CONS |--------------------->|CONS |
# |______| |______| |______|
# | | |
# ___v__ ___v__ ______ ______ ___v__ ______ ______
# |SETQ | |CONS |->|CONS |->|CONS | |CONS |->|CONS |->|CONS |
# |______| |______| |______| |______| |______| |______| |______|
# | | | | | |
# ___v__ ___v__ ___v__ ___v__ ___v__ ___v__
# |SYM f | |SYM x | |SYM y | |POWER | |SYM x | |SYM y |
# |______| |______| |______| |______| |______| |______|
#
# the result (in f) is a FUNCTION node
# that contains both the body and the argument list.
#
# We have
#
# caadr(p1) points to the function name i.e. f
# cdadr(p1) points to the arguments i.e. the list (x y)
# caddr(p1) points to the function body i.e. (power x y)
#define F p3 # F points to the function name
#define A p4 # A points to the argument list
#define B p5 # B points to the function body
define_user_function = ->
p3 = caadr(p1); # p3 is F
p4 = cdadr(p1); # p4 is A
p5 = caddr(p1); # p5 is B
if (!issymbol(p3)) # p3 is F
stop("function name?")
# evaluate function body (maybe)
if (car(p5) == symbol(EVAL)) # p5 is B
push(cadr(p5)); # p5 is B
Eval()
p5 = pop(); # p5 is B
# note how, unless explicitly forced by an eval,
# (handled by the if just above)
# we don't eval/simplify
# the body.
# Why? because it's the easiest way
# to solve scope problems i.e.
# x = 0
# f(x) = x + 1
# f(4) # would reply 1
# which would need to otherwise
# be solved by some scope device
# somehow
push_symbol(FUNCTION)
push p5
push p4
list(3)
p5 = pop()
set_binding(p3, p5); # p3 is F (function name) # p4 is A # p5 is B
# return value is nil
push_symbol(NIL)
Eval_function_reference = ->
push p1