Add 3 '*' operators: one prefix, one infix, and one postfix, per #523. (#582)

The presence or absence of whitespace is used to determine which
operator is in use, following the rules described in #520.

Support for prefix * dereference operator follows #523.

Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Richard Smith
2021-06-21 17:09:34 -07:00
committed by GitHub
co-authored by Geoff Romer
parent d6b47ba10f
commit 89e21113c3
12 changed files with 179 additions and 21 deletions
@@ -281,6 +281,9 @@ auto EvalPrim(Operator op, const std::vector<const Value*>& args, int line_num)
case Operator::Sub:
return Value::MakeIntVal(ValToInt(args[0], line_num) -
ValToInt(args[1], line_num));
case Operator::Mul:
return Value::MakeIntVal(ValToInt(args[0], line_num) *
ValToInt(args[1], line_num));
case Operator::Not:
return Value::MakeBoolVal(!ValToBool(args[0], line_num));
case Operator::And:
@@ -291,6 +294,11 @@ auto EvalPrim(Operator op, const std::vector<const Value*>& args, int line_num)
ValToBool(args[1], line_num));
case Operator::Eq:
return Value::MakeBoolVal(ValueEqual(args[0], args[1], line_num));
case Operator::Ptr:
return Value::MakePtrTypeVal(args[0]);
case Operator::Deref:
std::cerr << line_num << ": dereference not implemented yet\n";
exit(-1);
}
}
+33 -1
View File
@@ -30,6 +30,18 @@ void ExpectType(int line_num, const std::string& context, const Value* expected,
}
}
void ExpectPointerType(int line_num, const std::string& context,
const Value* actual) {
if (actual->tag != ValKind::PointerTV) {
std::cerr << line_num << ": type error in " << context << std::endl;
std::cerr << "expected a pointer type\n";
std::cerr << "actual: ";
PrintValue(actual, std::cerr);
std::cerr << std::endl;
exit(-1);
}
}
void PrintErrorString(const std::string& s) { std::cerr << s; }
void PrintTypeEnv(TypeEnv types, std::ostream& out) {
@@ -71,6 +83,9 @@ auto ReifyType(const Value* t, int line_num) -> const Expression* {
return Expression::MakeVar(0, *t->GetStructType().name);
case ValKind::ChoiceTV:
return Expression::MakeVar(0, *t->GetChoiceType().name);
case ValKind::PointerTV:
return Expression::MakeUnOp(
0, Operator::Ptr, ReifyType(t->GetPointerType().type, line_num));
default:
std::cerr << line_num << ": expected a type, not ";
PrintValue(t, std::cerr);
@@ -317,10 +332,21 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
ExpectType(e->line_num, "negation", Value::MakeIntTypeVal(), ts[0]);
return TCResult(new_e, Value::MakeIntTypeVal(), new_types);
case Operator::Add:
ExpectType(e->line_num, "addition(1)", Value::MakeIntTypeVal(),
ts[0]);
ExpectType(e->line_num, "addition(2)", Value::MakeIntTypeVal(),
ts[1]);
return TCResult(new_e, Value::MakeIntTypeVal(), new_types);
case Operator::Sub:
ExpectType(e->line_num, "subtraction(1)", Value::MakeIntTypeVal(),
ts[0]);
ExpectType(e->line_num, "substration(2)", Value::MakeIntTypeVal(),
ExpectType(e->line_num, "subtraction(2)", Value::MakeIntTypeVal(),
ts[1]);
return TCResult(new_e, Value::MakeIntTypeVal(), new_types);
case Operator::Mul:
ExpectType(e->line_num, "multiplication(1)", Value::MakeIntTypeVal(),
ts[0]);
ExpectType(e->line_num, "multiplication(2)", Value::MakeIntTypeVal(),
ts[1]);
return TCResult(new_e, Value::MakeIntTypeVal(), new_types);
case Operator::And:
@@ -337,6 +363,12 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values,
case Operator::Eq:
ExpectType(e->line_num, "==", ts[0], ts[1]);
return TCResult(new_e, Value::MakeBoolTypeVal(), new_types);
case Operator::Deref:
ExpectPointerType(e->line_num, "*", ts[0]);
return TCResult(new_e, ts[0]->GetPointerType().type, new_types);
case Operator::Ptr:
ExpectType(e->line_num, "*", Value::MakeTypeTypeVal(), ts[0]);
return TCResult(new_e, Value::MakeTypeTypeVal(), new_types);
}
break;
}
+1 -2
View File
@@ -357,9 +357,8 @@ auto PrintValue(const Value* val, std::ostream& out) -> void {
out << "Continuation";
break;
case ValKind::PointerTV:
out << "Ptr(";
PrintValue(val->GetPointerType().type, out);
out << ")";
out << "*";
break;
case ValKind::FunctionTV:
out << "fn ";