Class: Crisp::Functions::Core
- Inherits:
-
Object
- Object
- Crisp::Functions::Core
- Defined in:
- lib/crisp/functions/core.rb
Overview
Defining core crisp functions
Class Method Summary collapse
-
.load(current_env) ⇒ Object
load the functions and bind them into the given environment.
Class Method Details
.load(current_env) ⇒ Object
load the functions and bind them into the given environment
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/crisp/functions/core.rb', line 6 def self.load(current_env) # reserve nil/true/false in environment current_env['nil'] = nil current_env['true'] = true current_env['false'] = false # println # print arguments (seperated by whitspace) including a newline to the standard output # # (println 123) # 123 Function.new do print args_evaled.collect(&:to_s).join(' ') + "\n" end.bind('println', current_env) # def # bind the second argument to the symbol name of the first argument # actually a key/value pair will be stored in the environment # # (def foo 1) # => foo # (println foo) # 1 Function.new do validate_args_count(2, args.size) key = args[0].text_value value = args[1].resolve_and_eval(env) if value.class.name == "Crisp::Function" value.bind(key, env) else env[key] = value end end.bind('def', current_env) # fn # creates a function # the first argument has to be an array containing the argumentlist # the second argument is the function body # # (fn [a b] (+ a b) # => ...) Function.new do validate_args_count(2, args.size) if args[0].class.name != "Crisp::Nodes::ArrayLiteral" raise ArgumentError, "no argument list defined" end if args[1].class.name != "Crisp::Nodes::Operation" raise ArgumentError, "no function body defined" end fn_arg_list = args[0].raw_elements fn_operation = args[1] # create and return the new function Function.new do validate_args_count(fn_arg_list.size, args.size) local_env = Env.new fn_arg_list.each_with_index do |key, idx| local_env[key.text_value] = args[idx].resolve_and_eval(env) end chained_env = ChainedEnv.new(local_env, env) fn_operation.eval(chained_env) end end.bind('fn', current_env) # if # the if function evaluates the second argument if the condition (first argument) returns not nil or false. # Otherwise the third argument will be evaluated (optional) # # (if (= 1 2) 1 2) # => 2 Function.new do validate_args_count((2..3), args.size) result = args[0].resolve_and_eval(env) res = if ![nil, false].include?(result) args[1] elsif args[2] args[2] end res ? res.resolve_and_eval(env) : res end.bind('if', current_env) # . # perform a native call on an object with optional arguments # # (. upcase "abc") # => "ABC" Function.new do meth = args[0].text_value.to_sym target = args[1].resolve_and_eval(env) values = args[2..-1].map { |arg| arg.resolve_and_eval(env) } NativeCallInvoker.new(target, meth, values).invoke! end.bind('.', current_env) end |