algebrite
Version:
Computer Algebra System in Coffeescript
258 lines (216 loc) • 6.76 kB
text/coffeescript
# The symbol table is a simple array of struct U.
# put symbol at index n
Eval_symbolsinfo = ->
symbolsinfoToBePrinted = symbolsinfo()
if symbolsinfoToBePrinted != ""
new_string(symbolsinfoToBePrinted)
else
push_symbol(NIL)
symbolsinfo = ->
symbolsinfoToBePrinted = ""
for i in [NIL+1...symtab.length]
if symtab[i].printname == ""
if isSymbolReclaimable[i] == false
break
else
continue
symtabi = symtab[i] + ""
bindingi = (binding[i] + "").substring(0,4)
symbolsinfoToBePrinted += "symbol: " + symtabi + " size: " + countsize(binding[i]) + " value: " + bindingi + "...\n"
return symbolsinfoToBePrinted
# s is a string, n is an int
# TODO: elsewhere when we create a symbol we
# rather prefer to create a new entry. Here we just
# reuse the existing one. If that can never be a problem
# then explain why, otherwise do create a new entry.
std_symbol = (s, n, latexPrint) ->
p = symtab[n]
if !p?
debugger
p.printname = s
if latexPrint?
p.latexPrint = latexPrint
else
p.latexPrint = s
# symbol lookup, or symbol creation if symbol doesn't exist yet
# this happens often from the scanner. When the scanner sees something
# like myVar = 2, it create a tree (SETQ ("myVar" symbol as created/looked up here (2)))
# user-defined functions also have a usr symbol.
#
# Note that some symbols like, say, "abs",
# are picked up by the scanner directly as keywords,
# so they are not looked up via this.
# So in fact you could redefine abs to be abs(x) = x
# but still abs would be picked up by the scanner as a particular
# node type and calls to abs() will be always to the "native" abs
#
# Also note that some symbols such as "zero" are (strangely) not picked up by
# the scanner as special nodes, rather they are identified as keywords
# (e.g. not redefinable) at time of symbol lookup (in Eval_sym) and
# evalled, where eval has a case for ZERO.
#
# Also note that there are a number of symbols, such as a,b,c,x,y,z,...
# that are actually created by std_symbols.
# They are not special node types (like abs), they are normal symbols
# that are looked up, but the advantage is that since they are often
# used internally by algebrite, we create the symbol in advance and
# we can reference the symbol entry in a clean way
# (e.g. symbol(SYMBOL_X)) rather than
# by looking up a string.
# s is a string
usr_symbol = (s) ->
#console.log "usr_symbol of " + s
#if s == "aaa"
# debugger
# find either the existing symbol, or if we
# reach an empty symbol (printname == "") then
# re-use that location.
i = 0
for i in [0...NSYM]
if (symtab[i].printname == "")
# found an entry in the symbol table
# with no printname
break
if (s == symtab[i].printname)
return symtab[i]
if (i == NSYM)
stop("symbol table overflow")
symtab[i] = new U()
symtab[i].k = SYM
symtab[i].printname = s
# say that we just created the symbol
# then, binding[the new symbol entry]
# by default points to the symbol.
# So the value of an unassigned symbol will
# be just its name.
binding[i] = symtab[i]
isSymbolReclaimable[i] = false
return symtab[i]
# get the symbol's printname
# p is a U
get_printname = (p) ->
if (p.k != SYM)
stop("symbol error")
return p.printname
# p and q are both U
# there are two Us at play here. One belongs to the
# symtab array and is the variable name.
# The other one is the U with the content, and that
# one will go in the corresponding "binding" array entry.
set_binding = (p, q) ->
if (p.k != SYM)
stop("symbol error")
#console.log "setting binding of " + p.toString() + " to: " + q.toString()
#if p.toString() == "aaa"
# debugger
indexFound = symtab.indexOf(p)
###
if indexFound == -1
debugger
for i in [0...symtab.length]
if p.printname == symtab[i].printname
indexFound = i
console.log "remedied an index not found!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
break
###
if symtab.indexOf(p, indexFound + 1) != -1
console.log("ops, more than one element!")
debugger
if DEBUG then console.log("lookup >> set_binding lookup " + indexFound)
isSymbolReclaimable[indexFound] = false
binding[indexFound] = q
# p is a U
get_binding = (p) ->
if (p.k != SYM)
stop("symbol error")
#console.log "getting binding of " + p.toString()
#if p.toString() == "aaa"
# debugger
indexFound = symtab.indexOf(p)
###
if indexFound == -1
debugger
for i in [0...symtab.length]
if p.printname == symtab[i].printname
indexFound = i
console.log "remedied an index not found!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
break
###
if symtab.indexOf(p, indexFound + 1) != -1
console.log("ops, more than one element!")
debugger
if DEBUG then console.log("lookup >> get_binding lookup " + indexFound)
#if indexFound == 139
# debugger
#if indexFound == 137
# debugger
return binding[indexFound]
# the concept of user symbol is a little fuzzy
# beucase mathematics is full of symbols that actually
# have a special meaning, e.g. e,i,I in some cases j...
is_usr_symbol = (p) ->
if (p.k != SYM)
return false
theSymnum = symnum(p)
# see "defs" file for the naming of the symbols
if theSymnum > PI and theSymnum != SYMBOL_I and theSymnum != SYMBOL_IDENTITY_MATRIX
return true
return false
# get symbol's number from ptr
# p is U
lookupsTotal = 0
symnum = (p) ->
lookupsTotal++
if (p.k != SYM)
stop("symbol error")
indexFound = symtab.indexOf(p)
if symtab.indexOf(p, indexFound + 1) != -1
console.log("ops, more than one element!")
debugger
if DEBUG then console.log("lookup >> symnum lookup " + indexFound + " lookup # " + lookupsTotal)
#if lookupsTotal == 21
# debugger
#if indexFound == 79
# debugger
return indexFound
# push indexed symbol
# k is an int
push_symbol = (k) ->
push(symtab[k])
clear_symbols = ->
# we can clear just what's assignable.
# everything before NIL is not assignable,
# so there is no need to clear it.
for i in [NIL+1...NSYM]
# stop at the first empty
# entry that is not reclaimable
if symtab[i].printname == ""
if isSymbolReclaimable[i] == false
break
else
continue
symtab[i] = new U()
symtab[i].k = SYM
binding[i] = symtab[i]
isSymbolReclaimable[i] = false
#symtab[i].printname = ""
#binding[i] = symtab[i]
# collect all the variables in a tree
collectUserSymbols = (p, accumulator = []) ->
if is_usr_symbol(p)
if accumulator.indexOf(p) == -1
accumulator.push p
return
if (istensor(p))
for i in [0...p.tensor.nelem]
collectUserSymbols p.tensor.elem[i], accumulator
return
while (iscons(p))
collectUserSymbols(car(p), accumulator)
p = cdr(p)
return
$.get_binding = get_binding
$.set_binding = set_binding
$.usr_symbol = usr_symbol
$.symbolsinfo = symbolsinfo
$.collectUserSymbols = collectUserSymbols