Beispiel #1
0
bool
sEqP(ValuePtr lhs, ValuePtr rhs)
{
  if(lhs->type() != rhs->type()) return false;
  if(lhs->isBool() && lhs->vBool() == rhs->vBool()) return true;
  else if(lhs->isNumber() && lhs->isExact() && rhs->isExact() && lhs->vInt() == rhs->vInt()) return true;
  else if(lhs->isNumber() && !lhs->isExact() && !rhs->isExact() && lhs->vFloat() == rhs->vFloat()) return true;
  else if(lhs->isString() && string(lhs->vString()) == string(rhs->vString())) return true;
  else if(lhs->isSymbol() && string(lhs->vString()) == string(rhs->vString())) return true;
  else if(lhs->isPair() && (lhs == rhs || (lhs->isNull() && rhs->isNull()))) return true;
  else if(lhs->isProcedure() && (lhs.mValue == rhs.mValue)) return true;
  else if(lhs->type() == Value::UNDEFINED) return false;
  return false;
}
Beispiel #2
0
void
TestLibrary::numerical_operations()
{
  EnvPtr env = libraryEnvironment();
  ValuePtr result;
  // +
  result = eval(env, "(+ 1 2 3 4 5)");
  CHECK("Result is integer", result->isNumber() && result->isExact());
  CHECK_EQUAL("Value is correct", int, 15, result->vInt());

  // =
  result = eval(env, "(= 123 123 123)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(= 12.3 12.3 12.3)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(= 123 456 123)");
  CHECK("Result is false", result->isBool() && !result->vBool());  

  // <
  result = eval(env, "(< 1 2 3 4 5)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(< 1.0 2.0 3.0 4.0 5.0)");
  CHECK("Result is true", result->isBool() && result->vBool());  
  result = eval(env, "(< 6 5 4 3 2)");
  CHECK("Result is false", result->isBool() && !result->vBool());  
  result = eval(env, "(< 10 10 10)");
  CHECK("Result is false", result->isBool() && !result->vBool());  

  // >
  result = eval(env, "(> 6 5 4 3 2)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(> 5.0 4.0 3.0 2.0 1.0)");
  CHECK("Result is true", result->isBool() && result->vBool());  
  result = eval(env, "(> 1 2 3 4 5)");
  CHECK("Result is false", result->isBool() && !result->vBool());  
  result = eval(env, "(> 10 10 10)");
  CHECK("Result is false", result->isBool() && !result->vBool());  

  // <=
  result = eval(env, "(<= 1 2 4 4 5)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(<= 1.0 2.0 4.0 4.0 5.0)");
  CHECK("Result is true", result->isBool() && result->vBool());  
  result = eval(env, "(<= 6 5 4 3 2)");
  CHECK("Result is false", result->isBool() && !result->vBool());  

  // >=
  result = eval(env, "(>= 6 5 4 4 2)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(>= 5.0 4.0 4.0 2.0 1.0)");
  CHECK("Result is true", result->isBool() && result->vBool());  
  result = eval(env, "(>= 1 2 3 4 5)");
  CHECK("Result is false", result->isBool() && !result->vBool());  

  // number->string
  result = eval(env, "(number->string 10)");
  CHECK("Result is string", result->isString());
  CHECK_EQUAL("Correct value", string, "10", result->vString());
}
Beispiel #3
0
void
TestLibrary::strings()
{
  EnvPtr env = libraryEnvironment();
  ValuePtr result;

  // number->string
  result = eval(env, "(string-append \"abc\" \"def\")");
  CHECK("Result is string", result->isString());
  CHECK_EQUAL("Correct value", string, "abcdef", result->vString());
}
Beispiel #4
0
void
TestEval::eval_conditionals()
{
  EnvPtr env = libraryEnvironment();
  ValuePtr result = eval(env, "(if #t 'yes 'no)");
  CHECK("Symbol type", result->isSymbol());
  CHECK_EQUAL("Symbol result", string, "yes", result->vString());  
  
  result = eval(env, "(and '(foo) (= 10 10) 1)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(and '(foo) (= 10 20) 1)");
  CHECK("Result is false", result->isBool() && !result->vBool());

  result = eval(env, "(or (= 10 20) 10 1)");
  CHECK("Result is true", result->isBool() && result->vBool());
  result = eval(env, "(or #f (= 10 20) (< 10 5))");
  CHECK("Result is false", result->isBool() && !result->vBool());
}
Beispiel #5
0
void
TestEval::eval_simple()
{
  EnvPtr env = new Environment();
  env->parent = NULL;
  ValuePtr value;

  // bool false
  value = eval(env, "#f");
  CHECK("Boolean false", value->isBool() && !value->vBool());

  // integer
  value = eval(env, "#t");
  CHECK("Boolean true", value->isBool() && value->vBool());

  // integer
  value = eval(env, "123");
  CHECK("Integer type", value->isNumber() && value->isExact());
  CHECK_EQUAL("Integer content", int, 123, value->vInt());

  // double
  value = eval(env, "123.456");
  CHECK("Float type", value->isNumber() && !value->isExact());
  CHECK_EQUAL("Float content", float, 123.456, value->vFloat());

  // string
  value = eval(env, "\"foobar\"");
  CHECK("String type", value->isString());
  CHECK_EQUAL("string content", string, "foobar", value->vString());

  // Symbol
  ValuePtr intValue = new NumberValue(10);
  env->values["foo_symbol!"] = intValue;
  value = eval(env, "foo_symbol!");
  CHECK("Symbol lookup", intValue == value);

  // Quote
  value = eval(env, "'(foo)");
  CHECK("Pair type", value->isPair());
  CHECK("Empty list type", value->cdr()->isNull());
  CHECK("Symbol type", value->car()->isSymbol());
  CHECK_EQUAL("Symbol value", string, "foo", value->car()->vString());  
}
Beispiel #6
0
ValuePtr
evalLet(EnvPtr env, ValuePtr statement)
{
  EnvPtr letEnv = new Environment();
  letEnv->parent = env;
  ValuePtr bindings = statement->cdr()->car();
  CHECK("One or more expressions", sLength(statement) >= 3);
  CHECK("Let bindings are a list", sListP(bindings));
  while(bindings->isNull() == false) {
    CHECK("Let assignment is a list", sListP(bindings->car()));
    CHECK("Let assignment is a 2 item list", sLength(bindings->car()) == 2);
    ValuePtr variable = bindings->car()->car();
    CHECK("Assigning to a symbol", variable->isSymbol());
    ValuePtr value = eval(env, bindings->car()->cdr()->car());
    letEnv->values[variable->vString()] = value;
    bindings = bindings->cdr();
  }
  return evalSequence(letEnv, statement->cdr()->cdr());
}
Beispiel #7
0
ValuePtr
eval(EnvPtr env, ValuePtr data)
{
  // Self evaluating
  if(data->isBool() ||
     data->isNumber() ||
     data->isString()) {
    return data;
  }
  // Symbols
  else if(data->isSymbol()) {
    EnvPtr current = env;
    while(!(NULL == current)) {
      if(current->values.find(data->vString()) != current->values.end()) {
        return current->values[data->vString()];
      }
      current = current->parent;
    }
	CHECK_FAIL(string("Trying to access unknown symbol: ") + data->vString());
  }
  // Lists
  else if(data->isPair()) {
    if(!sListP(data)) {
      CHECK_FAIL("Unable to evaluate non-lists");
      return rsUndefined();
    }
    
    // ----------------------------------------
    // Check for special forms
    if(data->car()->isSymbol()) {

      // ----------------------------------------
      // Quote
      if(data->car()->vString() == string("quote")) {
        if(data->cdr()->isPair() &&
           data->cdr()->cdr()->isNull())
          return data->cdr()->car();
        else
          CHECK_FAIL("Quote error");
      }
      // ----------------------------------------
      // Lambda
      else if(data->car()->vString() == string("lambda")) {
        if(sListP(data->cdr()->car())) {
          return evalLambda(env, data->cdr()->car(), data->cdr()->cdr());
        }        
        else {
          CHECK_FAIL("Malformed lambda parameter sequence");
          return rsUndefined();
        }
      }
      // ----------------------------------------
      // Definitions: define, set!
      else if(data->car()->vString() == string("define")) {
        return evalDefine(env, data);
      }   
      else if(data->car()->vString() == string("set!")) {
        return evalSet(env, data);
      }      
      // ----------------------------------------
      // Conditionals and boolean: if, cond
      else if(data->car()->vString() == string("if")) {
        return evalIf(env, data);
      }
      else if(data->car()->vString() == string("cond")) {
        return evalCond(env, data);
      }
      else if(data->car()->vString() == string("and")) {
        return evalAnd(env, data);
      }
      else if(data->car()->vString() == string("or")) {
        return evalOr(env, data);
      }
      // ----------------------------------------
      // Binding constructs
      else if(data->car()->vString() == string("let")) {
        return evalLet(env, data);
      }      
      // ----------------------------------------
      // Sequencing
      else if(data->car()->vString() == string("begin")) {
        return evalSequence(env, data->cdr());
      }      
    }

    // Ok, standard statement
    return evalStatement(env, data);
  }  
  else {
    CHECK_FAIL("Trying to evaluate unknown type");
  }
  CHECK_FAIL("Eval error, this should never be reachable");
  return rsUndefined();
}