

Aug 29 19:13 2013 values_scheme.lua Page 1


--[[ Scheme Values Module
     KILT -- Kamin Interpreters in Lua Toolset
     H. Conrad Cunningham, Professor
     Computer and Information Science
     University of Mississippi

Developed for CSci 658, Software Language Engineering, Fall 2013

2013-08-19: Built Scheme module from Scheme interpreter code
2013-08-22: Moved treeConcat and printTree to new Utilities module
            Added require of Utilities module
            Corrected forward references to sxpToString, flattenList
2013-08-24: Added functions cons, decons, car, and cdr
            Modified conslist to use cons
2013-08-29: Changed to require Opcode Factory module

1234567890123456789012345678901234567890123456789012345678901234567890

--]]

-- KILT Interpreter Opcode Global Constants
local opcodes = require "opcodes"

-- KILT tree utilities library
local util = require "utilities"
local treeConcat = util.treeConcat


-- Function "hasOpCode" determines whether the first item in
-- array-style table "t" equals "op".  In particular, "op" is
-- expected to be one of the semantic opcodes.

local function hasOpCode(t,op)
  return (type(t) == "table" and t[1] == op)
end

-- BEGIN add for Lisp

-- ACCESS ATTRIBUTES OF S-EXPRESSIONS

-- Function "getNum" takes a semantic form "t". If "t" is a number,
-- it returns the enclosed number.

local function getNum(t)
  if hasOpCode(t,NUMSXP) and #t > 1 then
    return t[2]
  else
    return nil
  end
end

-- Function "getSym" takes a semantic form "t". If "t" is a symbol, it
-- returns the enclosed symbol (string).







Aug 29 19:13 2013 values_scheme.lua Page 2



local function getSym(t)
  if hasOpCode(t,SYMSXP) and #t > 1 then
    return t[2]
  else
    return nil
  end
end

-- BEGIN add for Scheme

-- Function "getPrim" takes a semantic form "t". If "t" is a builtin
-- primitive operator, it returns the enclosed operator.

local function getPrim(t)
  if hasOpCode(t,PRIMSXP) and #t > 1 then
    return t[2]
  else
    return nil
  end
end

-- END add for Scheme


-- CONS LIST FUNCTIONS AND CONSTANTS

-- Nil list "singleton" constant
local NILLIST = {NILSXP}

-- Function "cons" takes a head element "h" and a tail list "t" 
-- and returns a cons cell for the list with car "h" and cdr "t".

local function cons(h,t)
  if hasOpCode(t,LISTSXP) or t == NILLIST then
    return {LISTSXP; car = h, cdr = t}
  else
    error("Second operand of cons must be a list.")
  end
end
 
-- Function "decons" takes a cons list "l" and decomposes the cons
-- cell into its "op" component, where "op" is either "car" or 
-- "cdr".

local function decons(op,l)
  if hasOpCode(l,LISTSXP) then
    return l[op]
  else
    error(op .. " can only be applied to nonempty lists.")
  end
end








Aug 29 19:13 2013 values_scheme.lua Page 3


-- Functions "car" and "cdr" return the respective attributes of the
-- argument "l".

local function car(l) return decons("car",l) end
local function cdr(l) return decons("cdr",l) end

-- Function "consList" constructs a "cons" linked list from
-- array-style table "t" and returns it.

local function consList(t)
  if type(t) == "table" then
    local list = NILLIST
    for i = #t, 1, -1 do
      list = cons(t[i],list)
    end
    return list
  else
    error("Argument to consList is not a table: " .. tostring(t))
  end
end

-- END add for Lisp


-- HANDLE FALSE AND TRUE VALUES IN INTERPRETED LANGUAGE

-- The representation of the concepts false and true differs from one
-- of the Kamin interpreted languages to another and from the values
-- used by Lua.  The following constants and functions enable the Lua
-- program to manipulate the interpreted language "booleans".

-- BEGIN change for Lisp
-- local FALSEVAL = 0
-- local TRUEVAL  = 1
local FALSEVAL = NILLIST  -- make point to Nil list singleton object
local TRUEVAL  = {SYMSXP, "T"}
-- END change for Lisp

local function isFalse(v)
  return v == FALSEVAL
end

local function isTrue(v)
  return v ~= FALSEVAL
end

-- Function "boolAsVal" takes a Lua boolean (false or true) and
-- returns the corresponding value used in the interpreted language
-- (FALSEVAL or TRUEVAL).

local function boolAsVal(b) 
  if b then return TRUEVAL else return FALSEVAL end 
end







Aug 29 19:13 2013 values_scheme.lua Page 4




-- CONVERT LANGUAGE VALUES TO STRINGS

-- BEGIN add for Lisp
-- Local variables for function forward references
local sxpToString
local flattenList
-- END add for Lisp

-- Function "valToString converts value "v" to a string and 
-- returns it.

local function valToString(v)
  local tv = type(v)
  if tv == "string" then
    return v
  elseif tv == "number" then
    return tostring(v)
-- BEGIN add for Lisp
  elseif tv == "table" then
    return sxpToString(v)
-- END add for Lisp
  else
    return "Bad value:  " .. treeConcat(v)
  end
end

-- BEGIN add for Lisp

-- Function "sxpToString" converts an S-expression "v" to a string and
-- returns it.

sxpToString = function(v)
  if hasOpCode(v,NUMSXP) then
    return tostring(getNum(v))
  elseif hasOpCode(v,SYMSXP) then
    return getSym(v)
  elseif hasOpCode(v,NILSXP) then
    return "nil"
  elseif hasOpCode(v,LISTSXP) then
    local list = flattenList(v)
    return treeConcat(list)
-- BEGIN add for Scheme
  elseif hasOpCode(v,PRIMSXP) then
    return getPrim(v)
  elseif hasOpCode(v,CLOSXP) then
    return "<< closure >>"
-- END add for Scheme  else
  else
    return "Bad S-expression value:  " .. treeConcat(v)
  end
end







Aug 29 19:13 2013 values_scheme.lua Page 5



-- Function "flattenList" converts a "cons" linked list "list" into an
-- array-style table and returns it.

flattenList = function(list)
  if hasOpCode(list,LISTSXP) or list == NILLIST then
    local res = {}
    while list and list ~= NILLIST do
      res[#res+1] = valToString(list.car)
      list = list.cdr
    end
    return res
  else
    error("Argument to flattenList is not a list.")
  end
end

-- END add for Lisp


-- MODULE EXPORT LIST

return {
  FALSEVAL    = FALSEVAL,
  TRUEVAL     = TRUEVAL,
  isFalse     = isFalse,
  isTrue      = isTrue,
  boolAsVal   = boolAsVal,
  hasOpCode   = hasOpCode,
  valToString = valToString,
-- BEGIN add for Lisp
  sxpToString = sxpTotring,
  flattenList = flattenList,
  NILLIST     = NILLIST,
  cons        = cons,
  car         = car,
  cdr         = cdr,
  consList    = consList,
  getNum      = getNum,
  getSym      = getSym,
-- END add for Lisp
-- BEGIN add for Scheme
  getPrim     = getPrim
-- END add for Scheme
}













