LILAC
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
eval_lisp.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2014, Sam Schetterer, Nathan Kutz, University of Washington
3 Authors: Sam Schetterer
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 
8 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 
10 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
11 
12 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
13 
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 
16 */
17 #include "eval_lisp.h"
18 #include "engine/input.h"
19 #include "utils/defs.hpp"
20 #include "engine/item.h"
21 #include "engine/engineimp.h"
22 static std::set<std::string> get_keywords(){
23  std::set<std::string> vals;
24  vals.insert("@map");
25  return vals;
26 }
27 //ICC doesn't support initializer lists yet again
28 static std::set<std::string> keywords = get_keywords();
29 param_val split_into_toks(std::string param_vals, bool has_paren){
30  trim(param_vals);
31  param_val p_ret;
32  if(has_paren){
33  param_vals.erase(param_vals.end()-1);
34  param_vals.erase(param_vals.begin());
35  }
36  trim(param_vals);
37  ltoken(p_ret.type, param_vals);
38  ltoken(p_ret.name, param_vals);
39  trim(param_vals);
40  p_ret.params=param_vals;
41  return p_ret;
42 }
43 
44 std::list<std::string> split_into_sepxr(std::string in_expr){
45  size_t slen = in_expr.size();
46  size_t i = 0;
47  std::list<std::string> s_exp;
48  while(true){
49  while(in_expr[i] != '(' && i < slen){
50  i++;
51  }
52  if(i >= slen - 1){
53  break;
54  }
55  size_t start_paren=i;
56  i++;
57  size_t n_paren=1;
58  while(n_paren > 0 && i < slen){
59  if(in_expr[i] == ')'){
60  n_paren--;
61  }
62  else if(in_expr[i] == '('){
63  n_paren++;
64  }
65  i++;
66  }
67  if(n_paren > 0 || i > slen){
68  break;
69  }
70  s_exp.push_back(in_expr.substr(start_paren, i - start_paren));
71  }
72  return s_exp;
73 }
74 
76  std::map<std::string, input>& inv, engineimp* en){
77  if(in_cmd.empty()){
78  return std::shared_ptr<item>();
79  }
80  auto invals = split_into_toks(in_cmd);
81 
82  auto curit = item::create(invals.type, en);
83  if(invals.name.empty()){
84  std::cout<<"Variables need a name and a type, "<<
85  "error creating sub-variable for " << base_name << std::endl;
86  }
87  std::string n_prefix;
88  if(base_name.empty()){
89  n_prefix="";
90  }
91  else{
92  n_prefix=base_name+"::";
93  }
94  //get next token, should be variable name
95  curit->setname(n_prefix + invals.name);
96  inv[curit->name()] = input(en->values);
97  input& inval = inv[curit->name()];
98  item_wrapper c_wrap(curit);
99  auto native_ptr = std::dynamic_pointer_cast<native_item>(curit);
100  if(native_ptr.use_count()){
101  //if token is one of the native types, parse the input
102  native_ptr->parse(invals.params);
103  }
104  else{
105  //recursively evaluate whatever expression is passed on
106  for(auto& str : split_into_sepxr(invals.params)){
107  //this will check if special commands are being done
108  auto exp_tok=split_into_toks(str);
109  //should replace this with callbacks in the map
110  if(keywords.count(exp_tok.type)){
111  //remap the passed variable names to single name
112  if(exp_tok.type == "@map"){
113  std::string tok;
114  trim(exp_tok.params);
115  while(!exp_tok.params.empty()){
116  ltoken(tok, exp_tok.params);
117  inval.add_remap(exp_tok.name, tok);
118  c_wrap.replace_dep(exp_tok.name, tok);
119  }
120  }
121  }
122  else{
123  item_wrapper child_item = eval_lisp(str, n_prefix+invals.name, inv, en);
124  if(child_item.get_shared().use_count()){
125  //replace named dependencies with new fake names
126  param_val pp = split_into_toks(str);
127  c_wrap.replace_dep(child_item->name(), pp.name);
128  inval.add_redir(pp.name, child_item);
129  en->values[child_item->name()] = child_item;
130  }
131  }
132  }
133  }
134  return c_wrap;
135 }