<commit_before>#include <memory>
#include <cassert>

#include "eval.hh"
#include "util.hh"
#include "keyword.hh"
#include "symbol.hh"
#include "cons.hh"
#include "function.hh"
#include "printer.hh"

using namespace std;

enum class VM_op : int{
  nop = 0,
    if_,
    set_,
    funcall,
    arg_push,
    arg_bottom,
    interpreted_call,
    native_call,
    leave_frame
};

namespace {

inline
Symbol* to_varname(Lisp_ptr p){
  Symbol* var = p.get<Symbol*>();

  if(!var){
    fprintf(stderr, "eval error: variable's name is not a symbol!\n");
    return nullptr;
  }

  if(var->to_keyword() != Keyword::not_keyword){
    fprintf(stderr, "eval error: variable's name is Keyword (%s)!\n",
            var->name().c_str());
    return nullptr;
  }

  return var;
}

void vm_op_funcall(){
  auto proc = VM.return_value();
  auto args = VM.stack().top();
  VM.stack().pop();

  if(proc.tag() != Ptr_tag::function){
    fprintf(stderr, "eval error: (# # ...)'s first element is not procedure (%s)\n",
            stringify(proc.tag()));
    VM.return_value() = {};
    return;
  }

  auto fun = proc.get<Function*>();

  VM_op call_op;

  switch(fun->type()){
  case Function::Type::interpreted:
    call_op = VM_op::interpreted_call;
    break;
  case Function::Type::native:
    call_op = VM_op::native_call;
    break;
  default:
    UNEXP_DEFAULT();
  }

  VM.code().push(Lisp_ptr(proc));
  VM.code().push(Lisp_ptr(call_op));

  const auto& argi = fun->arg_info();
  int argc = 0;

  if(!do_list(args,
              [&](Cons* cell) -> bool{
                VM.code().push(Lisp_ptr(VM_op::arg_push));
                VM.code().push(cell->car());
                ++argc;

                return true;
              },
              [&](Lisp_ptr dot_cdr) -> bool{
                if(!nullp(dot_cdr)){
                  fprintf(stderr, "funcall error: arg-list is dot-list!\n");
                  return false;
                }

                if((argc < argi.required_args)
                   || (argi.variadic && argc > argi.required_args)){
                  fprintf(stderr, "funcall error: number of passed args is mismatched!! (required %d args, %s, passed %d)\n",
                          argi.required_args,
                          (argi.variadic) ? "variadic" : "not variadic",
                          argc);
                  return false;
                }

                return true;
              })){
    for(int i = 0; i < argc*2 + 2; ++i){
      VM.code().pop();
    }
    VM.stack().pop();
    VM.return_value() = {};
    return;
  }

  VM.stack().push(Lisp_ptr(VM_op::arg_bottom));
}

void vm_op_arg_push(){
  VM.stack().push(VM.return_value());
}

void vm_op_native_call(){
  auto proc = VM.code().top();
  VM.code().pop();
  auto fun = proc.get<Function*>();

  assert(fun->type() == Function::Type::native);

  fun->get<Function::NativeFunc>()();
  if(!VM.return_value())
    fprintf(stderr, "eval warning: native func returned undef!\n");
}

void vm_op_interpreted_call(){
  auto proc = VM.code().top();
  VM.code().pop();
  auto fun = proc.get<Function*>();

  assert(fun->type() == Function::Type::interpreted);
  assert(!VM.stack().empty());

  const auto& argi = fun->arg_info();

  // tail call check
  if(!VM.code().empty()
     && VM.code().top().get<VM_op>() == VM_op::leave_frame){
    VM.code().pop();
    VM.leave_frame();
  }

  VM.enter_frame(push_frame(fun->closure()));
  VM.code().push(Lisp_ptr(VM_op::leave_frame));

  Lisp_ptr arg_name = argi.head;
  Lisp_ptr st_top;

  while((st_top = VM.stack().top()).get<VM_op>() != VM_op::arg_bottom){
    VM.stack().pop();
    if(VM.stack().empty()){
      fprintf(stderr, "eval internal error: no args and no managed funcall!\n");
      VM.return_value() = {};
      return;
    }

    auto arg_name_cell = arg_name.get<Cons*>();
    if(arg_name_cell){
      VM.local_set(arg_name_cell->car().get<Symbol*>(), st_top);
      arg_name = arg_name_cell->cdr();
    }else{
      fprintf(stderr, "eval internal error: variadic call is under construction!\n");
      // variadic func's end
      break;
    }
  }

  assert(VM.stack().top().get<VM_op>() == VM_op::arg_bottom);
  VM.stack().pop();

  // set up lambda body code
  stack<Lisp_ptr, vector<Lisp_ptr>> tmp;

  if(!do_list(fun->get<Lisp_ptr>(),
              [&](Cons* c) -> bool {
                tmp.push(c->car());
                return true;
              },
              [&](Lisp_ptr last_cdr) -> bool{
                if(!nullp(last_cdr)){
                  fprintf(stderr, "eval error: body has dot list!\n");
                  return false;
                }
                return true;
              })){
    VM.return_value() = {};
    return;
  }

  while(!tmp.empty()){
    VM.code().push(tmp.top());
    tmp.pop();
  }
}

void vm_op_leave_frame(){
  VM.leave_frame();
}

void eval_lambda(const Cons* rest){
  VM.return_value() = {};

  auto args = rest->car();
  if(rest->cdr().tag() != Ptr_tag::cons){
    fprintf(stderr, "eval error: lambda has invalid body!\n");
    return;
  }

  auto arg_info = parse_func_arg(args);
  if(!arg_info){
    fprintf(stderr, "eval error: lambda has invalid args!\n");
    return;
  }

  auto code = rest->cdr();
  if(!code.get<Cons*>()){
    fprintf(stderr, "eval error: lambda has no body!\n");
    return;
  }

  auto fun = new Function(code, arg_info, VM.frame());

  VM.return_value() = Lisp_ptr{fun};
  return;
}

void eval_if(Cons* rest){
  VM.return_value() = {};

  // extracting
  Lisp_ptr test, conseq, alt;

  int len =
  bind_cons_list(Lisp_ptr(rest),
                 [&](Cons* c){
                   test = c->car();
                 },
                 [&](Cons* c){
                   conseq = c->car();
                 },
                 [&](Cons* c){
                   alt = c->car();
                 });

  switch(len){
  case 1:
    fprintf(stderr, "eval error: informal if expr! (no test expr)\n");
    return;
  case 2: case 3: // successed
    break;
  default:
    fprintf(stderr, "eval error: informal if expr! (more than %d exprs)\n", len);
    return;
  }

  // evaluating
  VM.code().push(Lisp_ptr(VM_op::if_));
  VM.code().push(test);

  VM.stack().push(alt);
  VM.stack().push(conseq);
}

void vm_op_if(){
  auto test_result = VM.return_value();

  if(test_result.get<bool>()){
    VM.code().push(VM.stack().top());
    VM.stack().pop();
    VM.stack().pop();
  }else{
    VM.stack().pop();
    VM.code().push(VM.stack().top());
    VM.stack().pop();
  }
}

void eval_set(Cons* rest){
  VM.return_value() = {};

  // extracting
  Symbol* var = nullptr;
  Lisp_ptr val;

  int len =
    bind_cons_list(Lisp_ptr(rest),
                   [&](Cons* c){
                     var = to_varname(c->car());
                   },
                   [&](Cons* c){
                     val = c->car();
                   });

  if(!var) return;

  if(!val){
    fprintf(stderr, "eval error: no value is supplied for set!\n");
    return;
  }

  if(len > 2){
    fprintf(stderr, "eval error: informal set! expr! (more than %d exprs)\n", len);
    return;
  }

  // evaluating
  VM.code().push(Lisp_ptr{VM_op::set_});
  VM.code().push(val);
  VM.stack().push(Lisp_ptr{var});
}

void vm_op_set(){
  auto var = VM.stack().top().get<Symbol*>();
  VM.stack().pop();
  if(!var){
    fprintf(stderr, "eval error: internal error occured (set!'s varname is dismissed)\n");
    return;
  }

  VM.set(var, VM.return_value());
}

void eval_define(const Cons* rest){
  VM.return_value() = {};

  // extracting
  auto first = rest->car();

  switch(first.tag()){
  case Ptr_tag::symbol: {
    auto var = to_varname(first);
    if(!var) return;

    auto val_l = rest->cdr().get<Cons*>();
    if(!val_l){
      fprintf(stderr, "eval error: definition has empty expr!\n");
      return;
    }
    if(val_l->cdr().tag() != Ptr_tag::cons
       || val_l->cdr().get<Cons*>()){
      fprintf(stderr, "eval error: definition has extra expr!\n");
      return;
    }

    VM.code().push(Lisp_ptr{VM_op::set_});
    VM.code().push(val_l->car());
    VM.stack().push(Lisp_ptr(var));
    return;
  }

  case Ptr_tag::cons: {
    auto lis = first.get<Cons*>();
    if(!lis){
      fprintf(stderr, "eval error: defined variable is not found!\n");
      return;
    }

    auto var = to_varname(lis->car());
    if(!var) return;

    const auto& arg_info = parse_func_arg(lis->cdr());
    if(!arg_info){
      fprintf(stderr, "eval error: defined function argument is informal!\n");
      return;
    }

    auto code = rest->cdr();
    if(!code.get<Cons*>()){
      fprintf(stderr, "eval error: definition has empty body!\n");
      return;
    }

    auto value = Lisp_ptr(new Function(code, arg_info, VM.frame()));
    VM.set(var, value);

    VM.return_value() = value;
    return;
  }

  default:
    fprintf(stderr, "eval error: informal define syntax!\n");
    return;
  }
}

} // namespace

void eval(){
  while(!VM.code().empty()){
    auto p = VM.code().top();
    VM.code().pop();

    switch(p.tag()){
    case Ptr_tag::symbol: {
      auto sym = to_varname(p);
      if(!sym){
        VM.return_value() = {};
        break;
      }

      VM.return_value() = VM.find(sym);
      break;
    }

    case Ptr_tag::cons: {
      auto c = p.get<Cons*>();
      auto first = c->car();

      // special operator?
      if(first.tag() == Ptr_tag::symbol){
        auto sym = first.get<Symbol*>();
        auto k = sym->to_keyword();

        if(k != Keyword::not_keyword){
          Cons* r = c->cdr().get<Cons*>();
          if(!r){
            fprintf(stderr, "eval error: expresssion (<KEYWORD>%s) is informal!\n",
                    (c->cdr().tag() == Ptr_tag::cons) ? "" : ". #");
            VM.return_value() = {};
            break;
          }

          switch(k){
          case Keyword::quote:  VM.return_value() = r->car(); break;
          case Keyword::lambda: eval_lambda(r); break;
          case Keyword::if_:    eval_if(r); break;
          case Keyword::set_:   eval_set(r); break;
          case Keyword::define: eval_define(r); break;

          case Keyword::cond:
          case Keyword::case_:
          case Keyword::and_:
          case Keyword::or_:
          case Keyword::let:
          case Keyword::let_star:
          case Keyword::letrec:
          case Keyword::begin:
          case Keyword::do_:
          case Keyword::delay:
          case Keyword::quasiquote:
            fprintf(stderr, "eval error: '%s' is under development...\n",
                    sym->name().c_str());
            VM.return_value() = {};
            break;

          case Keyword::else_:
          case Keyword::r_arrow:
          case Keyword::unquote:
          case Keyword::unquote_splicing:
            fprintf(stderr, "eval error: '%s' cannot be used as operator!!\n",
                    sym->name().c_str());
            VM.return_value() = {};
            break;

          default:
            UNEXP_DEFAULT();
          }
          break;
        }else{
          // macro call?
          //  try to find macro-function from symbol
          //    found -> macro expansion
          //    not found -> goto function calling
          ;
        }
      }

      // procedure call?
      VM.code().push(Lisp_ptr(VM_op::funcall));
      VM.code().push(first);
      VM.stack().push(c->cdr());
      break;
    }

    case Ptr_tag::vm_op:
      switch(p.get<VM_op>()){
      case VM_op::nop:
        break;
      case VM_op::if_:
        vm_op_if();
        break;
      case VM_op::set_:
        vm_op_set();
        break;
      case VM_op::funcall:
        vm_op_funcall();
        break;
      case VM_op::arg_push:
        vm_op_arg_push();
        break;
      case VM_op::interpreted_call:
        vm_op_interpreted_call();
        break;
      case VM_op::native_call:
        vm_op_native_call();
        break;
      case VM_op::leave_frame:
        vm_op_leave_frame();
        break;
      default:
        UNEXP_DEFAULT();
      }
      break;

    default: // almost self-evaluating
      VM.return_value() = p;
      break;
    }
  }
}
<commit_msg>added variadic arg call<commit_after>#include <memory>
#include <cassert>

#include "eval.hh"
#include "util.hh"
#include "keyword.hh"
#include "symbol.hh"
#include "cons.hh"
#include "function.hh"
#include "printer.hh"

using namespace std;

enum class VM_op : int{
  nop = 0,
    if_,
    set_,
    funcall,
    arg_push,
    arg_bottom,
    interpreted_call,
    native_call,
    leave_frame
};

namespace {

inline
Symbol* to_varname(Lisp_ptr p){
  Symbol* var = p.get<Symbol*>();

  if(!var){
    fprintf(stderr, "eval error: variable's name is not a symbol!\n");
    return nullptr;
  }

  if(var->to_keyword() != Keyword::not_keyword){
    fprintf(stderr, "eval error: variable's name is Keyword (%s)!\n",
            var->name().c_str());
    return nullptr;
  }

  return var;
}

void vm_op_funcall(){
  auto proc = VM.return_value();
  auto args = VM.stack().top();
  VM.stack().pop();

  if(proc.tag() != Ptr_tag::function){
    fprintf(stderr, "eval error: (# # ...)'s first element is not procedure (%s)\n",
            stringify(proc.tag()));
    VM.return_value() = {};
    return;
  }

  auto fun = proc.get<Function*>();

  VM_op call_op;

  switch(fun->type()){
  case Function::Type::interpreted:
    call_op = VM_op::interpreted_call;
    break;
  case Function::Type::native:
    call_op = VM_op::native_call;
    break;
  default:
    UNEXP_DEFAULT();
  }

  VM.code().push(Lisp_ptr(proc));
  VM.code().push(Lisp_ptr(call_op));

  const auto& argi = fun->arg_info();
  int argc = 0;

  if(!do_list(args,
              [&](Cons* cell) -> bool{
                VM.code().push(Lisp_ptr(VM_op::arg_push));
                VM.code().push(cell->car());
                ++argc;

                return true;
              },
              [&](Lisp_ptr dot_cdr) -> bool{
                if(!nullp(dot_cdr)){
                  fprintf(stderr, "funcall error: arg-list is dot-list!\n");
                  return false;
                }

                if((argc < argi.required_args)
                   || (argi.variadic && argc > argi.required_args)){
                  fprintf(stderr, "funcall error: number of passed args is mismatched!! (required %d args, %s, passed %d)\n",
                          argi.required_args,
                          (argi.variadic) ? "variadic" : "not variadic",
                          argc);
                  return false;
                }

                return true;
              })){
    for(int i = 0; i < argc*2 + 2; ++i){
      VM.code().pop();
    }
    VM.stack().pop();
    VM.return_value() = {};
    return;
  }

  VM.stack().push(Lisp_ptr(VM_op::arg_bottom));
}

void vm_op_arg_push(){
  VM.stack().push(VM.return_value());
}

void vm_op_native_call(){
  auto proc = VM.code().top();
  VM.code().pop();
  auto fun = proc.get<Function*>();

  assert(fun->type() == Function::Type::native);

  fun->get<Function::NativeFunc>()();
  if(!VM.return_value())
    fprintf(stderr, "eval warning: native func returned undef!\n");
}

void vm_op_interpreted_call(){
  auto proc = VM.code().top();
  VM.code().pop();
  auto fun = proc.get<Function*>();

  assert(fun->type() == Function::Type::interpreted);
  assert(!VM.stack().empty());

  const auto& argi = fun->arg_info();

  // tail call check
  if(!VM.code().empty()
     && VM.code().top().get<VM_op>() == VM_op::leave_frame){
    VM.code().pop();
    VM.leave_frame();
  }

  VM.enter_frame(push_frame(fun->closure()));
  VM.code().push(Lisp_ptr(VM_op::leave_frame));

  Lisp_ptr arg_name = argi.head;
  Lisp_ptr st_top;

  // normal arg push
  while((st_top = VM.stack().top()).get<VM_op>() != VM_op::arg_bottom){
    VM.stack().pop();
    if(VM.stack().empty()){
      fprintf(stderr, "eval internal error: no args and no managed funcall!\n");
      VM.return_value() = {};
      return;
    }

    auto arg_name_cell = arg_name.get<Cons*>();
    if(!arg_name_cell){
      break;
    }

    VM.local_set(arg_name_cell->car().get<Symbol*>(), st_top);
    arg_name = arg_name_cell->cdr();
  }

  // variadic arg push
  if(argi.variadic){
    if(!arg_name.get<Symbol*>()){
      fprintf(stderr, "eval error: no arg name for variadic arg!\n");
      VM.return_value() = {};
      return;
    }

    Cons* head = new Cons;
    Cons* c = head;

    while(!VM.stack().empty()
          && (st_top = VM.stack().top()).get<VM_op>() != VM_op::arg_bottom){
      VM.stack().pop();

      c->rplaca(st_top);
      Cons* cc = new Cons;
      c->rplacd(Lisp_ptr(cc));
      c = cc;
    }

    c->rplaca(Cons::NIL);
    VM.local_set(arg_name.get<Symbol*>(), Lisp_ptr(head));
  }

  // clean stack
  if(VM.stack().empty()
     || VM.stack().top().get<VM_op>() != VM_op::arg_bottom){
    fprintf(stderr, "eval error: corrupted stack -- no bottom found!\n");
    VM.return_value() = {};
    return;
  }
  VM.stack().pop();

  // set up lambda body code
  stack<Lisp_ptr, vector<Lisp_ptr>> tmp;

  if(!do_list(fun->get<Lisp_ptr>(),
              [&](Cons* c) -> bool {
                tmp.push(c->car());
                return true;
              },
              [&](Lisp_ptr last_cdr) -> bool{
                if(!nullp(last_cdr)){
                  fprintf(stderr, "eval error: body has dot list!\n");
                  return false;
                }
                return true;
              })){
    VM.return_value() = {};
    return;
  }

  while(!tmp.empty()){
    VM.code().push(tmp.top());
    tmp.pop();
  }
}

void vm_op_leave_frame(){
  VM.leave_frame();
}

void eval_lambda(const Cons* rest){
  VM.return_value() = {};

  auto args = rest->car();
  if(rest->cdr().tag() != Ptr_tag::cons){
    fprintf(stderr, "eval error: lambda has invalid body!\n");
    return;
  }

  auto arg_info = parse_func_arg(args);
  if(!arg_info){
    fprintf(stderr, "eval error: lambda has invalid args!\n");
    return;
  }

  auto code = rest->cdr();
  if(!code.get<Cons*>()){
    fprintf(stderr, "eval error: lambda has no body!\n");
    return;
  }

  auto fun = new Function(code, arg_info, VM.frame());

  VM.return_value() = Lisp_ptr{fun};
  return;
}

void eval_if(Cons* rest){
  VM.return_value() = {};

  // extracting
  Lisp_ptr test, conseq, alt;

  int len =
  bind_cons_list(Lisp_ptr(rest),
                 [&](Cons* c){
                   test = c->car();
                 },
                 [&](Cons* c){
                   conseq = c->car();
                 },
                 [&](Cons* c){
                   alt = c->car();
                 });

  switch(len){
  case 1:
    fprintf(stderr, "eval error: informal if expr! (no test expr)\n");
    return;
  case 2: case 3: // successed
    break;
  default:
    fprintf(stderr, "eval error: informal if expr! (more than %d exprs)\n", len);
    return;
  }

  // evaluating
  VM.code().push(Lisp_ptr(VM_op::if_));
  VM.code().push(test);

  VM.stack().push(alt);
  VM.stack().push(conseq);
}

void vm_op_if(){
  auto test_result = VM.return_value();

  if(test_result.get<bool>()){
    VM.code().push(VM.stack().top());
    VM.stack().pop();
    VM.stack().pop();
  }else{
    VM.stack().pop();
    VM.code().push(VM.stack().top());
    VM.stack().pop();
  }
}

void eval_set(Cons* rest){
  VM.return_value() = {};

  // extracting
  Symbol* var = nullptr;
  Lisp_ptr val;

  int len =
    bind_cons_list(Lisp_ptr(rest),
                   [&](Cons* c){
                     var = to_varname(c->car());
                   },
                   [&](Cons* c){
                     val = c->car();
                   });

  if(!var) return;

  if(!val){
    fprintf(stderr, "eval error: no value is supplied for set!\n");
    return;
  }

  if(len > 2){
    fprintf(stderr, "eval error: informal set! expr! (more than %d exprs)\n", len);
    return;
  }

  // evaluating
  VM.code().push(Lisp_ptr{VM_op::set_});
  VM.code().push(val);
  VM.stack().push(Lisp_ptr{var});
}

void vm_op_set(){
  auto var = VM.stack().top().get<Symbol*>();
  VM.stack().pop();
  if(!var){
    fprintf(stderr, "eval error: internal error occured (set!'s varname is dismissed)\n");
    return;
  }

  VM.set(var, VM.return_value());
}

void eval_define(const Cons* rest){
  VM.return_value() = {};

  // extracting
  auto first = rest->car();

  switch(first.tag()){
  case Ptr_tag::symbol: {
    auto var = to_varname(first);
    if(!var) return;

    auto val_l = rest->cdr().get<Cons*>();
    if(!val_l){
      fprintf(stderr, "eval error: definition has empty expr!\n");
      return;
    }
    if(val_l->cdr().tag() != Ptr_tag::cons
       || val_l->cdr().get<Cons*>()){
      fprintf(stderr, "eval error: definition has extra expr!\n");
      return;
    }

    VM.code().push(Lisp_ptr{VM_op::set_});
    VM.code().push(val_l->car());
    VM.stack().push(Lisp_ptr(var));
    return;
  }

  case Ptr_tag::cons: {
    auto lis = first.get<Cons*>();
    if(!lis){
      fprintf(stderr, "eval error: defined variable is not found!\n");
      return;
    }

    auto var = to_varname(lis->car());
    if(!var) return;

    const auto& arg_info = parse_func_arg(lis->cdr());
    if(!arg_info){
      fprintf(stderr, "eval error: defined function argument is informal!\n");
      return;
    }

    auto code = rest->cdr();
    if(!code.get<Cons*>()){
      fprintf(stderr, "eval error: definition has empty body!\n");
      return;
    }

    auto value = Lisp_ptr(new Function(code, arg_info, VM.frame()));
    VM.set(var, value);

    VM.return_value() = value;
    return;
  }

  default:
    fprintf(stderr, "eval error: informal define syntax!\n");
    return;
  }
}

} // namespace

void eval(){
  while(!VM.code().empty()){
    auto p = VM.code().top();
    VM.code().pop();

    switch(p.tag()){
    case Ptr_tag::symbol: {
      auto sym = to_varname(p);
      if(!sym){
        VM.return_value() = {};
        break;
      }

      VM.return_value() = VM.find(sym);
      break;
    }

    case Ptr_tag::cons: {
      auto c = p.get<Cons*>();
      auto first = c->car();

      // special operator?
      if(first.tag() == Ptr_tag::symbol){
        auto sym = first.get<Symbol*>();
        auto k = sym->to_keyword();

        if(k != Keyword::not_keyword){
          Cons* r = c->cdr().get<Cons*>();
          if(!r){
            fprintf(stderr, "eval error: expresssion (<KEYWORD>%s) is informal!\n",
                    (c->cdr().tag() == Ptr_tag::cons) ? "" : ". #");
            VM.return_value() = {};
            break;
          }

          switch(k){
          case Keyword::quote:  VM.return_value() = r->car(); break;
          case Keyword::lambda: eval_lambda(r); break;
          case Keyword::if_:    eval_if(r); break;
          case Keyword::set_:   eval_set(r); break;
          case Keyword::define: eval_define(r); break;

          case Keyword::cond:
          case Keyword::case_:
          case Keyword::and_:
          case Keyword::or_:
          case Keyword::let:
          case Keyword::let_star:
          case Keyword::letrec:
          case Keyword::begin:
          case Keyword::do_:
          case Keyword::delay:
          case Keyword::quasiquote:
            fprintf(stderr, "eval error: '%s' is under development...\n",
                    sym->name().c_str());
            VM.return_value() = {};
            break;

          case Keyword::else_:
          case Keyword::r_arrow:
          case Keyword::unquote:
          case Keyword::unquote_splicing:
            fprintf(stderr, "eval error: '%s' cannot be used as operator!!\n",
                    sym->name().c_str());
            VM.return_value() = {};
            break;

          default:
            UNEXP_DEFAULT();
          }
          break;
        }else{
          // macro call?
          //  try to find macro-function from symbol
          //    found -> macro expansion
          //    not found -> goto function calling
          ;
        }
      }

      // procedure call?
      VM.code().push(Lisp_ptr(VM_op::funcall));
      VM.code().push(first);
      VM.stack().push(c->cdr());
      break;
    }

    case Ptr_tag::vm_op:
      switch(p.get<VM_op>()){
      case VM_op::nop:
        break;
      case VM_op::if_:
        vm_op_if();
        break;
      case VM_op::set_:
        vm_op_set();
        break;
      case VM_op::funcall:
        vm_op_funcall();
        break;
      case VM_op::arg_push:
        vm_op_arg_push();
        break;
      case VM_op::interpreted_call:
        vm_op_interpreted_call();
        break;
      case VM_op::native_call:
        vm_op_native_call();
        break;
      case VM_op::leave_frame:
        vm_op_leave_frame();
        break;
      default:
        UNEXP_DEFAULT();
      }
      break;

    default: // almost self-evaluating
      VM.return_value() = p;
      break;
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - 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.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * 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
 * OWNER 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.
 */

#include <system.hh>

#include "expr.h"
#include "parser.h"

namespace ledger {

void expr_t::parse(std::istream& in, const parse_flags_t& flags,
                   const optional<string>& original_string)
{
  parser_t parser;
  istream_pos_type start_pos = in.tellg();
  ptr = parser.parse(in, flags, original_string);
  istream_pos_type end_pos = in.tellg();

  if (original_string) {
    set_text(*original_string);
  }
  else if (end_pos > start_pos) {
    in.clear();
    in.seekg(start_pos, std::ios::beg);
    scoped_array<char> buf
      (new char[static_cast<std::size_t>(end_pos - start_pos) + 1]);
    in.read(buf.get(), end_pos - start_pos);
    buf[end_pos - start_pos] = '\0';
    set_text(buf.get());
  }
  else {
    set_text("<stream>");
  }
}

void expr_t::compile(scope_t& scope)
{
  if (! compiled && ptr) {
    ptr = ptr->compile(scope);
    base_type::compile(scope);
  }
}

value_t expr_t::real_calc(scope_t& scope)
{
  if (ptr) {
    ptr_op_t locus;
    try {
      return ptr->calc(scope, &locus);
    }
    catch (const std::exception&) {
      if (locus) {
        string current_context = error_context();

        add_error_context(_("While evaluating value expression:"));
        add_error_context(op_context(ptr, locus));

        if (SHOW_INFO()) {
          add_error_context(_("The value expression tree was:"));
          std::ostringstream buf;
          ptr->dump(buf, 0);

          std::istringstream in(buf.str());
          std::ostringstream out;
          char linebuf[1024];
          bool first = true;
          while (in.good() && ! in.eof()) {
            in.getline(linebuf, 1023);
            std::streamsize len = in.gcount();
            if (len > 0) {
              if (first)
                first = false;
              else
                out << '\n';
              out << "  " << linebuf;
            }
          }
          add_error_context(out.str());
        }

        if (! current_context.empty())
          add_error_context(current_context);
      }
      throw;
    }
  }
  return NULL_VALUE;
}

bool expr_t::is_constant() const
{
  assert(compiled);
  return ptr && ptr->is_value();
}

bool expr_t::is_function() const
{
  assert(compiled);
  return ptr && ptr->is_function();
}

value_t& expr_t::constant_value()
{
  assert(is_constant());
  return ptr->as_value_lval();
}

const value_t& expr_t::constant_value() const
{
  assert(is_constant());
  return ptr->as_value();
}

expr_t::func_t& expr_t::get_function()
{
  assert(is_function());
  return ptr->as_function_lval();
}

string expr_t::context_to_str() const
{
  return ptr ? op_context(ptr) : _("<empty expression>");
}

void expr_t::print(std::ostream& out) const
{
  if (ptr)
    ptr->print(out);
}

void expr_t::dump(std::ostream& out) const
{
  if (ptr) ptr->dump(out, 0);
}

} // namespace ledger
<commit_msg>Corrected a compilation warning<commit_after>/*
 * Copyright (c) 2003-2010, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - 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.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * 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
 * OWNER 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.
 */

#include <system.hh>

#include "expr.h"
#include "parser.h"

namespace ledger {

void expr_t::parse(std::istream& in, const parse_flags_t& flags,
                   const optional<string>& original_string)
{
  parser_t parser;
  istream_pos_type start_pos = in.tellg();
  ptr = parser.parse(in, flags, original_string);
  istream_pos_type end_pos = in.tellg();

  if (original_string) {
    set_text(*original_string);
  }
  else if (end_pos > start_pos) {
    in.clear();
    in.seekg(start_pos, std::ios::beg);
    scoped_array<char> buf
      (new char[static_cast<std::size_t>(end_pos - start_pos) + 1]);
    int len = static_cast<int>(end_pos) - static_cast<int>(start_pos);
    in.read(buf.get(), len);
    buf[len] = '\0';
    set_text(buf.get());
  }
  else {
    set_text("<stream>");
  }
}

void expr_t::compile(scope_t& scope)
{
  if (! compiled && ptr) {
    ptr = ptr->compile(scope);
    base_type::compile(scope);
  }
}

value_t expr_t::real_calc(scope_t& scope)
{
  if (ptr) {
    ptr_op_t locus;
    try {
      return ptr->calc(scope, &locus);
    }
    catch (const std::exception&) {
      if (locus) {
        string current_context = error_context();

        add_error_context(_("While evaluating value expression:"));
        add_error_context(op_context(ptr, locus));

        if (SHOW_INFO()) {
          add_error_context(_("The value expression tree was:"));
          std::ostringstream buf;
          ptr->dump(buf, 0);

          std::istringstream in(buf.str());
          std::ostringstream out;
          char linebuf[1024];
          bool first = true;
          while (in.good() && ! in.eof()) {
            in.getline(linebuf, 1023);
            std::streamsize len = in.gcount();
            if (len > 0) {
              if (first)
                first = false;
              else
                out << '\n';
              out << "  " << linebuf;
            }
          }
          add_error_context(out.str());
        }

        if (! current_context.empty())
          add_error_context(current_context);
      }
      throw;
    }
  }
  return NULL_VALUE;
}

bool expr_t::is_constant() const
{
  assert(compiled);
  return ptr && ptr->is_value();
}

bool expr_t::is_function() const
{
  assert(compiled);
  return ptr && ptr->is_function();
}

value_t& expr_t::constant_value()
{
  assert(is_constant());
  return ptr->as_value_lval();
}

const value_t& expr_t::constant_value() const
{
  assert(is_constant());
  return ptr->as_value();
}

expr_t::func_t& expr_t::get_function()
{
  assert(is_function());
  return ptr->as_function_lval();
}

string expr_t::context_to_str() const
{
  return ptr ? op_context(ptr) : _("<empty expression>");
}

void expr_t::print(std::ostream& out) const
{
  if (ptr)
    ptr->print(out);
}

void expr_t::dump(std::ostream& out) const
{
  if (ptr) ptr->dump(out, 0);
}

} // namespace ledger
<|endoftext|>


<commit_before>/*
 * PrecisionLaserKnifeImplementation.cpp
 *
 *  Created on: Mar 8, 2011
 *      Author: polonel
 */

#include "PrecisionLaserKnife.h"
#include "server/zone/packets/scene/AttributeListMessage.h"
#include "server/zone/ZoneServer.h"
#include "server/zone/objects/player/sessions/SlicingSession.h"
#include "server/zone/managers/gcw/GCWManager.h"
#include "server/zone/Zone.h"
int PrecisionLaserKnifeImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {

	if (!isASubChildOf(player))
		return 0;

	if(!player->hasSkill("combat_smuggler_novice")){
		player->sendSystemMessage("You must be at least a Novice Smuggler to use this tool.");
		return 0;
	}

	if (selectedID != 20)
		return TangibleObjectImplementation::handleObjectMenuSelect(player, selectedID);

	uint64 targetID = player->getTargetID();
	ZoneServer* zs = player->getZoneServer();
	ManagedReference<TangibleObject*> target = dynamic_cast<TangibleObject*>(zs->getObject(targetID, true));

	if (target == NULL || (!target->isSliceable() && !target->isSecurityTerminal())) {
		player->sendSystemMessage("You cannot slice that.");
		return 0;
	}

	if (target->isMissionTerminal() && !player->hasSkill("combat_smuggler_novice"))
		return 0;
	else if (target->isWeaponObject() && !player->hasSkill("combat_smuggler_slicing_02"))
		return 0;
	else if (target->isArmorObject() && !player->hasSkill("combat_smuggler_slicing_03"))
		return 0;
	else if (target->isSecurityTerminal()){
		Zone* zone = target->getZone();
		if(zone == NULL)
			return 0;

		GCWManager* gcwMan = zone->getGCWManager();
		if(gcwMan == NULL)
			return 0;

		if(!gcwMan->canStartSlice(player, target))
			return 0;

	}

	if (target->isSliced()) {
		player->sendSystemMessage("@slicing/slicing:already_sliced");
		return 0;
	}

	if (player->containsActiveSession(SessionFacadeType::SLICING)) {
		player->sendSystemMessage("@slicing/slicing:already_slicing");
		return 0;
	}

	if (!player->checkCooldownRecovery("slicing.terminal")) {
		player->sendSystemMessage("@slicing/slicing:not_again");
		return 0;
	}

	//Create Session
	ManagedReference<SlicingSession*> session = new SlicingSession(player);

	if(target->isSecurityTerminal())
		session->setBaseSlice(true);

	session->initalizeSlicingMenu(player, target);

	useCharge(player);

	return 0;
}

void PrecisionLaserKnifeImplementation::fillAttributeList(AttributeListMessage* msg, CreatureObject* object) {
	SlicingToolImplementation::fillAttributeList(msg, object);

	msg->insertAttribute("charges", charges);

}

void PrecisionLaserKnifeImplementation::updateCharges(int val) {
	charges = val;
	AttributeListMessage* msg = new AttributeListMessage(getObjectID());
	msg->insertAttribute("charges", charges);
	broadcastMessage(msg, false);
}
<commit_msg>[fixed] Laser knives now only use charges when cutting a wire - Mantis 3894<commit_after>/*
 * PrecisionLaserKnifeImplementation.cpp
 *
 *  Created on: Mar 8, 2011
 *      Author: polonel
 */

#include "PrecisionLaserKnife.h"
#include "server/zone/packets/scene/AttributeListMessage.h"
#include "server/zone/ZoneServer.h"
#include "server/zone/objects/player/sessions/SlicingSession.h"
#include "server/zone/managers/gcw/GCWManager.h"
#include "server/zone/Zone.h"
int PrecisionLaserKnifeImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {

	if (!isASubChildOf(player))
		return 0;

	if(!player->hasSkill("combat_smuggler_novice")){
		player->sendSystemMessage("You must be at least a Novice Smuggler to use this tool.");
		return 0;
	}

	if (selectedID != 20)
		return TangibleObjectImplementation::handleObjectMenuSelect(player, selectedID);

	uint64 targetID = player->getTargetID();
	ZoneServer* zs = player->getZoneServer();
	ManagedReference<TangibleObject*> target = dynamic_cast<TangibleObject*>(zs->getObject(targetID, true));

	if (target == NULL || (!target->isSliceable() && !target->isSecurityTerminal())) {
		player->sendSystemMessage("You cannot slice that.");
		return 0;
	}

	if (target->isMissionTerminal() && !player->hasSkill("combat_smuggler_novice"))
		return 0;
	else if (target->isWeaponObject() && !player->hasSkill("combat_smuggler_slicing_02"))
		return 0;
	else if (target->isArmorObject() && !player->hasSkill("combat_smuggler_slicing_03"))
		return 0;
	else if (target->isSecurityTerminal()){
		Zone* zone = target->getZone();
		if(zone == NULL)
			return 0;

		GCWManager* gcwMan = zone->getGCWManager();
		if(gcwMan == NULL)
			return 0;

		if(!gcwMan->canStartSlice(player, target))
			return 0;

	}

	if (target->isSliced()) {
		player->sendSystemMessage("@slicing/slicing:already_sliced");
		return 0;
	}

	if (player->containsActiveSession(SessionFacadeType::SLICING)) {
		player->sendSystemMessage("@slicing/slicing:already_slicing");
		return 0;
	}

	if (!player->checkCooldownRecovery("slicing.terminal")) {
		player->sendSystemMessage("@slicing/slicing:not_again");
		return 0;
	}

	//Create Session
	ManagedReference<SlicingSession*> session = new SlicingSession(player);

	if(target->isSecurityTerminal())
		session->setBaseSlice(true);

	session->initalizeSlicingMenu(player, target);

	//useCharge(player);

	return 0;
}

void PrecisionLaserKnifeImplementation::fillAttributeList(AttributeListMessage* msg, CreatureObject* object) {
	SlicingToolImplementation::fillAttributeList(msg, object);

	msg->insertAttribute("charges", charges);

}

void PrecisionLaserKnifeImplementation::updateCharges(int val) {
	charges = val;
	AttributeListMessage* msg = new AttributeListMessage(getObjectID());
	msg->insertAttribute("charges", charges);
	broadcastMessage(msg, false);
}
<|endoftext|>


<commit_before>/*

    OF-TangibleFramework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef _GRID
#define _GRID

class Grid{
    private:
        /// opengl list index
        int grid_list;
        int arrows_list;
        int w_lines;
        int h_lines;
    public:
        Grid(int _w_lines, int _h_lines);
        ~Grid();
        void Draw(bool calibration_enabled, int calibration_mode);
        void Resize();
    private:
        void GenerateOpenGL_lists();
        void RenderArrow_one(int size);
        void RenderArrow_two(int size);
        void DrawArrow_three(int size);
};

#endif
<commit_msg>code cleaning<commit_after>/*

    OF-TangibleFramework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Daniel Gallardo Grassot <daniel.gallardo@upf.edu>

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use,
    copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following
    conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.

*/

#ifndef _GRID
#define _GRID

class Grid{
    private:
        /// opengl list index
        int grid_list;
        int w_lines;
        int h_lines;
    public:
        Grid(int _w_lines, int _h_lines);
        ~Grid();
        void Draw(bool calibration_enabled, int calibration_mode);
        void Resize();
    private:
        void GenerateOpenGL_lists();
        void RenderArrow_one(int size);
        void RenderArrow_two(int size);
        void DrawArrow_three(int size);
};

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sharedformulabuffer.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2008-01-17 08:06:09 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "oox/xls/sharedformulabuffer.hxx"
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include "oox/helper/recordinputstream.hxx"
#include "oox/xls/addressconverter.hxx"
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/defnamesbuffer.hxx"
#include "oox/xls/formulaparser.hxx"

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::table::CellAddress;
using ::com::sun::star::table::CellRangeAddress;
using ::com::sun::star::sheet::XFormulaTokens;
using ::com::sun::star::sheet::XNamedRange;

namespace oox {
namespace xls {

// ============================================================================

namespace {

bool operator==( const CellAddress& rAddr1, const CellAddress& rAddr2 )
{
    return
        (rAddr1.Sheet == rAddr2.Sheet) &&
        (rAddr1.Column == rAddr2.Column) &&
        (rAddr1.Row == rAddr2.Row);
}

bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr )
{
    return
        (rRange.Sheet == rAddr.Sheet) &&
        (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) &&
        (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow);
}

} // namespace

// ============================================================================

ExtCellFormulaContext::ExtCellFormulaContext( const WorksheetHelper& rHelper,
        const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) :
    SimpleFormulaContext( rxTokens, false, false ),
    WorksheetHelper( rHelper )
{
    setBaseAddress( rCellPos );
}

void ExtCellFormulaContext::setSharedFormula( const CellAddress& rBaseAddr )
{
    getSharedFormulas().setSharedFormulaCell( *this, rBaseAddr );
}

// ============================================================================

SharedFormulaBuffer::SharedFormulaBuffer( const WorksheetHelper& rHelper ) :
    WorksheetHelper( rHelper )
{
}

void SharedFormulaBuffer::importSharedFmla( const OUString& rFormula, const OUString& rSharedRange, sal_Int32 nSharedId, const CellAddress& rBaseAddr )
{
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, rSharedRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( nSharedId, 0 );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // convert the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rFormula );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::importSharedFmla( RecordInputStream& rStrm, const CellAddress& rBaseAddr )
{
    BinRange aRange;
    rStrm >> aRange;
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( rBaseAddr );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // load the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rStrm );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::importSharedFmla( BiffInputStream& rStrm, const CellAddress& rBaseAddr )
{
    BinRange aRange;
    aRange.read( rStrm, false );        // always 8bit column indexes
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( rBaseAddr );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // load the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            rStrm.skip( 2 );    // flags
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rStrm );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, const CellAddress& rBaseAddr )
{
    if( !implSetSharedFormulaCell( rContext, BinAddress( rBaseAddr ) ) )
        if( rContext.getBaseAddress() == rBaseAddr )
            mxLastContext.reset( new ExtCellFormulaContext( rContext ) );
}

void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, sal_Int32 nSharedId )
{
    implSetSharedFormulaCell( rContext, BinAddress( nSharedId, 0 ) );
}

Reference< XNamedRange > SharedFormulaBuffer::createDefinedName( const BinAddress& rMapKey )
{
    OSL_ENSURE( maIndexMap.count( rMapKey ) == 0, "SharedFormulaBuffer::createDefinedName - shared formula exists already" );
    // create the defined name representing the shared formula
    OUString aName = OUStringBuffer().appendAscii( "__shared_" ).
        append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ).
        append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
        append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
    Reference< XNamedRange > xNamedRange = getDefinedNames().createDefinedName( aName );
    sal_Int32 nTokenIndex = getDefinedNames().getTokenIndex( xNamedRange );
    if( nTokenIndex >= 0 )
        maIndexMap[ rMapKey ] = nTokenIndex;
    return xNamedRange;
}

bool SharedFormulaBuffer::implSetSharedFormulaCell( ExtCellFormulaContext& rContext, const BinAddress& rMapKey )
{
    TokenIndexMap::const_iterator aIt = maIndexMap.find( rMapKey );
    sal_Int32 nTokenIndex = (aIt == maIndexMap.end()) ? -1 : aIt->second;
    if( nTokenIndex >= 0 )
    {
        getFormulaParser().convertNameToFormula( rContext, nTokenIndex );
        return true;
    }
    return false;
}

void SharedFormulaBuffer::updateCachedCell( const CellAddress& rBaseAddr, const BinAddress& rMapKey )
{
    if( mxLastContext.get() && (mxLastContext->getBaseAddress() == rBaseAddr) )
        implSetSharedFormulaCell( *mxLastContext, rMapKey );
    mxLastContext.reset();
}

// ============================================================================

} // namespace xls
} // namespace oox

<commit_msg>INTEGRATION: CWS xmlfilter03_DEV300 (1.2.4); FILE MERGED 2008/02/06 11:00:57 dr 1.2.4.1: shared formula property for defined names<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sharedformulabuffer.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-05 19:05:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "oox/xls/sharedformulabuffer.hxx"
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/sheet/XFormulaTokens.hpp>
#include "oox/helper/propertyset.hxx"
#include "oox/helper/recordinputstream.hxx"
#include "oox/xls/addressconverter.hxx"
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/defnamesbuffer.hxx"
#include "oox/xls/formulaparser.hxx"

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::table::CellAddress;
using ::com::sun::star::table::CellRangeAddress;
using ::com::sun::star::sheet::XFormulaTokens;
using ::com::sun::star::sheet::XNamedRange;

namespace oox {
namespace xls {

// ============================================================================

namespace {

bool operator==( const CellAddress& rAddr1, const CellAddress& rAddr2 )
{
    return
        (rAddr1.Sheet == rAddr2.Sheet) &&
        (rAddr1.Column == rAddr2.Column) &&
        (rAddr1.Row == rAddr2.Row);
}

bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr )
{
    return
        (rRange.Sheet == rAddr.Sheet) &&
        (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) &&
        (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow);
}

} // namespace

// ============================================================================

ExtCellFormulaContext::ExtCellFormulaContext( const WorksheetHelper& rHelper,
        const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) :
    SimpleFormulaContext( rxTokens, false, false ),
    WorksheetHelper( rHelper )
{
    setBaseAddress( rCellPos );
}

void ExtCellFormulaContext::setSharedFormula( const CellAddress& rBaseAddr )
{
    getSharedFormulas().setSharedFormulaCell( *this, rBaseAddr );
}

// ============================================================================

SharedFormulaBuffer::SharedFormulaBuffer( const WorksheetHelper& rHelper ) :
    WorksheetHelper( rHelper ),
    maIsSharedProp( CREATE_OUSTRING( "IsSharedFormula" ) )
{
}

void SharedFormulaBuffer::importSharedFmla( const OUString& rFormula, const OUString& rSharedRange, sal_Int32 nSharedId, const CellAddress& rBaseAddr )
{
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, rSharedRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( nSharedId, 0 );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // convert the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rFormula );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::importSharedFmla( RecordInputStream& rStrm, const CellAddress& rBaseAddr )
{
    BinRange aRange;
    rStrm >> aRange;
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( rBaseAddr );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // load the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rStrm );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::importSharedFmla( BiffInputStream& rStrm, const CellAddress& rBaseAddr )
{
    BinRange aRange;
    aRange.read( rStrm, false );        // always 8bit column indexes
    CellRangeAddress aFmlaRange;
    if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true ) )
    {
        // create the defined name representing the shared formula
        OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
        BinAddress aMapKey( rBaseAddr );
        Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey );
        // load the formula definition
        Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY );
        if( xTokens.is() )
        {
            rStrm.skip( 2 );    // flags
            SimpleFormulaContext aContext( xTokens, true, false );
            aContext.setBaseAddress( rBaseAddr );
            getFormulaParser().importFormula( aContext, rStrm );
            updateCachedCell( rBaseAddr, aMapKey );
        }
    }
}

void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, const CellAddress& rBaseAddr )
{
    if( !implSetSharedFormulaCell( rContext, BinAddress( rBaseAddr ) ) )
        if( rContext.getBaseAddress() == rBaseAddr )
            mxLastContext.reset( new ExtCellFormulaContext( rContext ) );
}

void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, sal_Int32 nSharedId )
{
    implSetSharedFormulaCell( rContext, BinAddress( nSharedId, 0 ) );
}

Reference< XNamedRange > SharedFormulaBuffer::createDefinedName( const BinAddress& rMapKey )
{
    OSL_ENSURE( maIndexMap.count( rMapKey ) == 0, "SharedFormulaBuffer::createDefinedName - shared formula exists already" );
    // create the defined name representing the shared formula
    OUString aName = OUStringBuffer().appendAscii( "__shared_" ).
        append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ).
        append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
        append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
    Reference< XNamedRange > xNamedRange = getDefinedNames().createDefinedName( aName );
    PropertySet aNameProps( xNamedRange );
    aNameProps.setProperty( maIsSharedProp, true );
    sal_Int32 nTokenIndex = getDefinedNames().getTokenIndex( xNamedRange );
    if( nTokenIndex >= 0 )
        maIndexMap[ rMapKey ] = nTokenIndex;
    return xNamedRange;
}

bool SharedFormulaBuffer::implSetSharedFormulaCell( ExtCellFormulaContext& rContext, const BinAddress& rMapKey )
{
    TokenIndexMap::const_iterator aIt = maIndexMap.find( rMapKey );
    sal_Int32 nTokenIndex = (aIt == maIndexMap.end()) ? -1 : aIt->second;
    if( nTokenIndex >= 0 )
    {
        getFormulaParser().convertNameToFormula( rContext, nTokenIndex );
        return true;
    }
    return false;
}

void SharedFormulaBuffer::updateCachedCell( const CellAddress& rBaseAddr, const BinAddress& rMapKey )
{
    if( mxLastContext.get() && (mxLastContext->getBaseAddress() == rBaseAddr) )
        implSetSharedFormulaCell( *mxLastContext, rMapKey );
    mxLastContext.reset();
}

// ============================================================================

} // namespace xls
} // namespace oox

<|endoftext|>


<commit_before>/*
 * UREConfigReader.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Nil Geisweiller <ngeiswei@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "UREConfigReader.h"

#include <opencog/atoms/NumberNode.h>
#include <opencog/query/BindLinkAPI.h>
#include <opencog/atomspaceutils/AtomSpaceUtils.h>

using namespace std;
using namespace opencog;

const std::string UREConfigReader::top_rbs_name = "URE";

// Parameters
const std::string UREConfigReader::attention_alloc_name = "URE:attention-allocation";
const std::string UREConfigReader::max_iter_name = "URE:maximum-iterations";
const std::string UREConfigReader::bc_complexity_penalty_name = "URE:BC:complexity-penalty";
const std::string UREConfigReader::bc_max_bit_size_name = "URE:BC:max-bit-size";

UREConfigReader::UREConfigReader(AtomSpace& as, const Handle& rbs) : _as(as)
{
	//////////////////////////
	// Common parameters    //
	//////////////////////////

	if (Handle::UNDEFINED == rbs)
		throw RuntimeException(TRACE_INFO,
			"UREConfigReader - invalid rulebase specified!");

	// Retrieve the rules (MemberLinks) and instantiate them
	for (const Handle& rule_name : fetch_rule_names(rbs))
		_common_params.rules.emplace(rule_name, rbs);

	// Fetch maximum number of iterations
	_common_params.max_iter = fetch_num_param(max_iter_name, rbs);

	// Fetch attention allocation parameter
	_common_params.attention_alloc = fetch_bool_param(attention_alloc_name, rbs);

	//////////////////////
	// FC parameters    //
	//////////////////////

	//////////////////////
	// BC parameters    //
	//////////////////////

	// Fetch BC complexity penalty parameter
	_bc_params.complexity_penalty = fetch_num_param(bc_complexity_penalty_name, rbs);

	// Fetch BC BIT maximum size parameter
	_bc_params.max_bit_size = fetch_num_param(bc_max_bit_size_name, rbs, -1);
}

const RuleSet& UREConfigReader::get_rules() const
{
	return _common_params.rules;
}

RuleSet& UREConfigReader::get_rules()
{
	return _common_params.rules;
}

bool UREConfigReader::get_attention_allocation() const
{
	return _common_params.attention_alloc;
}

int UREConfigReader::get_maximum_iterations() const
{
	return _common_params.max_iter;
}

double UREConfigReader::get_complexity_penalty() const
{
	return _bc_params.complexity_penalty;
}

double UREConfigReader::get_max_bit_size() const
{
	return _bc_params.max_bit_size;
}

void UREConfigReader::set_attention_allocation(bool aa)
{
	_common_params.attention_alloc = aa;
}

void UREConfigReader::set_maximum_iterations(int mi)
{
	_common_params.max_iter = mi;
}

void UREConfigReader::set_complexity_penalty(double cp)
{
	_bc_params.complexity_penalty = cp;
}

HandleSeq UREConfigReader::fetch_rule_names(const Handle& rbs)
{
	// Retrieve rules
	Handle rule_var = _as.add_node(VARIABLE_NODE, "__URE_RULE__"),
		rule_pat = _as.add_link(MEMBER_LINK, rule_var, rbs),
		gl = _as.add_link(GET_LINK, rule_pat),
		results = satisfying_set(&_as, gl);
	HandleSeq rule_names = results->getOutgoingSet();

	// Remove the GetLink pattern and other no longer useful atoms
	// from the AtomSpace
	extract_hypergraph(_as, gl);
	_as.extract_atom(results);

	return rule_names;
}

HandleSeq UREConfigReader::fetch_execution_outputs(const Handle& schema,
                                                   const Handle& input,
                                                   Type type)
{
	// Retrieve rules
	Handle var_node = _as.add_node(VARIABLE_NODE, "__EXECUTION_OUTPUT_VAR__"),
		type_node = _as.add_node(TYPE_NODE, classserver().getTypeName(type)),
		typed_var = _as.add_link(TYPED_VARIABLE_LINK, var_node, type_node),
		gl = _as.add_link(GET_LINK,
		                  // TypedVariableLink
		                  //    var_node
		                  //    type_node
		                  typed_var,
		                  // ExecutionLink
		                  //    <schema>
		                  //    <input>
		                  //    var_node
		                  _as.add_link(EXECUTION_LINK,
		                               schema,
		                               input,
		                               var_node)),
		results = satisfying_set(&_as, gl);
	HandleSeq outputs = results->getOutgoingSet();

	// Remove the GetLink pattern and other no longer useful atoms
	// from the AtomSpace
	extract_hypergraph(_as, gl);
	_as.extract_atom(results);

	return outputs;
}

double UREConfigReader::fetch_num_param(const string& schema_name,
                                        const Handle& input,
                                        double default_value)
{
	Handle param_schema = _as.add_node(SCHEMA_NODE, schema_name);
	HandleSeq outputs = fetch_execution_outputs(param_schema, input, NUMBER_NODE);
	{
		string input_name = input->getName();
		Type input_type = input->getType();
		string input_str =
			classserver().getTypeName(input_type) + " \"" + input_name + "\"";
		if (outputs.size() == 0) {
			logger().warn() << "Could not retrieve parameter " << schema_name
			                << " for rule-based system " << input_name
			                << ". Use default value " << default_value
			                << " instead.";
			return default_value;
		} else {
			OC_ASSERT(outputs.size() == 1,
		          "Could not retrieve parameter %s for rule-based system %s. "
		          "There should be only one output for\n"
		          "ExecutionLink\n"
		          "   SchemaNode \"%s\"\n"
		          "   %s\n"
		          "   <N>\n"
		          "instead there are %u",
		          schema_name.c_str(), input_name.c_str(),
		          schema_name.c_str(), input_str.c_str(), outputs.size());
			return NumberNodeCast(outputs.front())->get_value();
		}
	}
}

bool UREConfigReader::fetch_bool_param(const string& pred_name,
                                       const Handle& input)
{
	Handle pred = _as.add_node(PREDICATE_NODE, pred_name);
	TruthValuePtr tv =
		_as.add_link(EVALUATION_LINK, pred, input)->getTruthValue();
	return tv->getMean() > 0.5;
}
<commit_msg>Have max bit size param name more consistent<commit_after>/*
 * UREConfigReader.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Nil Geisweiller <ngeiswei@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "UREConfigReader.h"

#include <opencog/atoms/NumberNode.h>
#include <opencog/query/BindLinkAPI.h>
#include <opencog/atomspaceutils/AtomSpaceUtils.h>

using namespace std;
using namespace opencog;

const std::string UREConfigReader::top_rbs_name = "URE";

// Parameters
const std::string UREConfigReader::attention_alloc_name = "URE:attention-allocation";
const std::string UREConfigReader::max_iter_name = "URE:maximum-iterations";
const std::string UREConfigReader::bc_complexity_penalty_name = "URE:BC:complexity-penalty";
const std::string UREConfigReader::bc_max_bit_size_name = "URE:BC:maximum-bit-size";

UREConfigReader::UREConfigReader(AtomSpace& as, const Handle& rbs) : _as(as)
{
	//////////////////////////
	// Common parameters    //
	//////////////////////////

	if (Handle::UNDEFINED == rbs)
		throw RuntimeException(TRACE_INFO,
			"UREConfigReader - invalid rulebase specified!");

	// Retrieve the rules (MemberLinks) and instantiate them
	for (const Handle& rule_name : fetch_rule_names(rbs))
		_common_params.rules.emplace(rule_name, rbs);

	// Fetch maximum number of iterations
	_common_params.max_iter = fetch_num_param(max_iter_name, rbs);

	// Fetch attention allocation parameter
	_common_params.attention_alloc = fetch_bool_param(attention_alloc_name, rbs);

	//////////////////////
	// FC parameters    //
	//////////////////////

	//////////////////////
	// BC parameters    //
	//////////////////////

	// Fetch BC complexity penalty parameter
	_bc_params.complexity_penalty = fetch_num_param(bc_complexity_penalty_name, rbs);

	// Fetch BC BIT maximum size parameter
	_bc_params.max_bit_size = fetch_num_param(bc_max_bit_size_name, rbs, -1);
}

const RuleSet& UREConfigReader::get_rules() const
{
	return _common_params.rules;
}

RuleSet& UREConfigReader::get_rules()
{
	return _common_params.rules;
}

bool UREConfigReader::get_attention_allocation() const
{
	return _common_params.attention_alloc;
}

int UREConfigReader::get_maximum_iterations() const
{
	return _common_params.max_iter;
}

double UREConfigReader::get_complexity_penalty() const
{
	return _bc_params.complexity_penalty;
}

double UREConfigReader::get_max_bit_size() const
{
	return _bc_params.max_bit_size;
}

void UREConfigReader::set_attention_allocation(bool aa)
{
	_common_params.attention_alloc = aa;
}

void UREConfigReader::set_maximum_iterations(int mi)
{
	_common_params.max_iter = mi;
}

void UREConfigReader::set_complexity_penalty(double cp)
{
	_bc_params.complexity_penalty = cp;
}

HandleSeq UREConfigReader::fetch_rule_names(const Handle& rbs)
{
	// Retrieve rules
	Handle rule_var = _as.add_node(VARIABLE_NODE, "__URE_RULE__"),
		rule_pat = _as.add_link(MEMBER_LINK, rule_var, rbs),
		gl = _as.add_link(GET_LINK, rule_pat),
		results = satisfying_set(&_as, gl);
	HandleSeq rule_names = results->getOutgoingSet();

	// Remove the GetLink pattern and other no longer useful atoms
	// from the AtomSpace
	extract_hypergraph(_as, gl);
	_as.extract_atom(results);

	return rule_names;
}

HandleSeq UREConfigReader::fetch_execution_outputs(const Handle& schema,
                                                   const Handle& input,
                                                   Type type)
{
	// Retrieve rules
	Handle var_node = _as.add_node(VARIABLE_NODE, "__EXECUTION_OUTPUT_VAR__"),
		type_node = _as.add_node(TYPE_NODE, classserver().getTypeName(type)),
		typed_var = _as.add_link(TYPED_VARIABLE_LINK, var_node, type_node),
		gl = _as.add_link(GET_LINK,
		                  // TypedVariableLink
		                  //    var_node
		                  //    type_node
		                  typed_var,
		                  // ExecutionLink
		                  //    <schema>
		                  //    <input>
		                  //    var_node
		                  _as.add_link(EXECUTION_LINK,
		                               schema,
		                               input,
		                               var_node)),
		results = satisfying_set(&_as, gl);
	HandleSeq outputs = results->getOutgoingSet();

	// Remove the GetLink pattern and other no longer useful atoms
	// from the AtomSpace
	extract_hypergraph(_as, gl);
	_as.extract_atom(results);

	return outputs;
}

double UREConfigReader::fetch_num_param(const string& schema_name,
                                        const Handle& input,
                                        double default_value)
{
	Handle param_schema = _as.add_node(SCHEMA_NODE, schema_name);
	HandleSeq outputs = fetch_execution_outputs(param_schema, input, NUMBER_NODE);
	{
		string input_name = input->getName();
		Type input_type = input->getType();
		string input_str =
			classserver().getTypeName(input_type) + " \"" + input_name + "\"";
		if (outputs.size() == 0) {
			logger().warn() << "Could not retrieve parameter " << schema_name
			                << " for rule-based system " << input_name
			                << ". Use default value " << default_value
			                << " instead.";
			return default_value;
		} else {
			OC_ASSERT(outputs.size() == 1,
		          "Could not retrieve parameter %s for rule-based system %s. "
		          "There should be only one output for\n"
		          "ExecutionLink\n"
		          "   SchemaNode \"%s\"\n"
		          "   %s\n"
		          "   <N>\n"
		          "instead there are %u",
		          schema_name.c_str(), input_name.c_str(),
		          schema_name.c_str(), input_str.c_str(), outputs.size());
			return NumberNodeCast(outputs.front())->get_value();
		}
	}
}

bool UREConfigReader::fetch_bool_param(const string& pred_name,
                                       const Handle& input)
{
	Handle pred = _as.add_node(PREDICATE_NODE, pred_name);
	TruthValuePtr tv =
		_as.add_link(EVALUATION_LINK, pred, input)->getTruthValue();
	return tv->getMean() > 0.5;
}
<|endoftext|>


<commit_before>#include "selfdrive/ui/qt/widgets/toggle.h"

#include <QPainter>

Toggle::Toggle(QWidget *parent) : QAbstractButton(parent),
_height(80),
_height_rect(60),
on(false),
_anim(new QPropertyAnimation(this, "offset_circle", this))
{
  _radius = _height / 2;
  _x_circle = _radius;
  _y_circle = _radius;
  _y_rect = (_height - _height_rect)/2;
  circleColor = QColor(0xffffff); // placeholder
  green = QColor(0xffffff); // placeholder
  setEnabled(true);
}

void Toggle::paintEvent(QPaintEvent *e) {
  this->setFixedHeight(_height);
  QPainter p(this);
  p.setPen(Qt::NoPen);
  p.setRenderHint(QPainter::Antialiasing, true);

  // Draw toggle background left
  p.setBrush(green);
  p.drawRoundedRect(QRect(0, _y_rect, _x_circle + _radius, _height_rect), _height_rect/2, _height_rect/2);

  // Draw toggle background right
  p.setBrush(QColor(0x393939));
  p.drawRoundedRect(QRect(_x_circle - _radius, _y_rect, width() - (_x_circle - _radius), _height_rect), _height_rect/2, _height_rect/2);

  // Draw toggle circle
  p.setBrush(circleColor);
  p.drawEllipse(QRectF(_x_circle - _radius, _y_circle - _radius, 2 * _radius, 2 * _radius));
}

void Toggle::mouseReleaseEvent(QMouseEvent *e) {
  if(!enabled) {
    return;
  }
  const int left = _radius;
  const int right = width() - _radius;
  if(_x_circle != left && _x_circle != right) {
    //Don't parse touch events, while the animation is running
    return;
  }
  if (e->button() & Qt::LeftButton) {
    togglePosition();
    emit stateChanged(on);
  }
}

void Toggle::togglePosition() {
  on = !on;
  const int left = _radius;
  const int right = width() - _radius;
  _anim->setStartValue(on ? left + immediateOffset : right - immediateOffset);
  _anim->setEndValue(on ? right : left);
  _anim->setDuration(animation_duration);
  _anim->start();
  repaint();
}

void Toggle::enterEvent(QEvent *e) {
  QAbstractButton::enterEvent(e);
}

bool Toggle::getEnabled() {
  return enabled;
}

void Toggle::setEnabled(bool value) {
  enabled = value;
  if(value) {
    circleColor.setRgb(0xfafafa);
    green.setRgb(0x33ab4c);
  }else{
    circleColor.setRgb(0x888888);
    green.setRgb(0x227722);
  }
}<commit_msg>toggles: released -> clicked (#21786)<commit_after>#include "selfdrive/ui/qt/widgets/toggle.h"

#include <QPainter>

Toggle::Toggle(QWidget *parent) : QAbstractButton(parent),
_height(80),
_height_rect(60),
on(false),
_anim(new QPropertyAnimation(this, "offset_circle", this))
{
  _radius = _height / 2;
  _x_circle = _radius;
  _y_circle = _radius;
  _y_rect = (_height - _height_rect)/2;
  circleColor = QColor(0xffffff); // placeholder
  green = QColor(0xffffff); // placeholder
  setEnabled(true);
}

void Toggle::paintEvent(QPaintEvent *e) {
  this->setFixedHeight(_height);
  QPainter p(this);
  p.setPen(Qt::NoPen);
  p.setRenderHint(QPainter::Antialiasing, true);

  // Draw toggle background left
  p.setBrush(green);
  p.drawRoundedRect(QRect(0, _y_rect, _x_circle + _radius, _height_rect), _height_rect/2, _height_rect/2);

  // Draw toggle background right
  p.setBrush(QColor(0x393939));
  p.drawRoundedRect(QRect(_x_circle - _radius, _y_rect, width() - (_x_circle - _radius), _height_rect), _height_rect/2, _height_rect/2);

  // Draw toggle circle
  p.setBrush(circleColor);
  p.drawEllipse(QRectF(_x_circle - _radius, _y_circle - _radius, 2 * _radius, 2 * _radius));
}

void Toggle::mouseReleaseEvent(QMouseEvent *e) {
  if (!enabled) {
    return;
  }
  const int left = _radius;
  const int right = width() - _radius;
  if ((_x_circle != left && _x_circle != right) || !this->rect().contains(e->localPos().toPoint())) {
    // If mouse release isn't in rect or animation is running, don't parse touch events
    return;
  }
  if (e->button() & Qt::LeftButton) {
    togglePosition();
    emit stateChanged(on);
  }
}

void Toggle::togglePosition() {
  on = !on;
  const int left = _radius;
  const int right = width() - _radius;
  _anim->setStartValue(on ? left + immediateOffset : right - immediateOffset);
  _anim->setEndValue(on ? right : left);
  _anim->setDuration(animation_duration);
  _anim->start();
  repaint();
}

void Toggle::enterEvent(QEvent *e) {
  QAbstractButton::enterEvent(e);
}

bool Toggle::getEnabled() {
  return enabled;
}

void Toggle::setEnabled(bool value) {
  enabled = value;
  if(value) {
    circleColor.setRgb(0xfafafa);
    green.setRgb(0x33ab4c);
  }else{
    circleColor.setRgb(0x888888);
    green.setRgb(0x227722);
  }
}
<|endoftext|>