Skip to content

Commit

Permalink
Add 3 '*' operators: one prefix, one infix, and one postfix.
Browse files Browse the repository at this point in the history
The presence or absence of whitespace is used to determine which
operator is in use.
  • Loading branch information
zygoloid committed May 13, 2021
1 parent ca2693d commit 16f10e3
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 11 deletions.
1 change: 1 addition & 0 deletions executable_semantics/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ EXAMPLES = [
"pattern_init",
"pattern_variable_fail",
"record1",
"star",
"struct1",
"struct2",
"struct3",
Expand Down
9 changes: 6 additions & 3 deletions executable_semantics/ast/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,15 +245,18 @@ auto Expression::MakeIndex(int line_num, const Expression* exp,

static void PrintOp(Operator op) {
switch (op) {
case Operator::Neg:
std::cout << "-";
break;
case Operator::Add:
std::cout << "+";
break;
case Operator::Neg:
case Operator::Sub:
std::cout << "-";
break;
case Operator::Mul:
case Operator::Deref:
case Operator::Ptr:
std::cout << "*";
break;
case Operator::Not:
std::cout << "not";
break;
Expand Down
3 changes: 3 additions & 0 deletions executable_semantics/ast/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ enum class ExpressionKind {
enum class Operator {
Add,
And,
Deref,
Eq,
Mul,
Neg,
Not,
Or,
Sub,
Ptr,
};

struct Expression;
Expand Down
8 changes: 8 additions & 0 deletions executable_semantics/interpreter/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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);
}
}

Expand Down
34 changes: 33 additions & 1 deletion executable_semantics/interpreter/typecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand All @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions executable_semantics/interpreter/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 ";
Expand Down
27 changes: 24 additions & 3 deletions executable_semantics/syntax/lexer.lpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
%option yylineno

%s AFTER_WHITESPACE

AND "and"
ARROW "->"
AUTO "auto"
Expand Down Expand Up @@ -53,13 +55,16 @@ AWAIT "__await"
identifier [A-Za-z_][A-Za-z0-9_]*
integer_literal [0-9]+
horizontal_whitespace [ \t\r]
whitespace [ \t\r\n]

%{
// This macro is expanded to run each time a token is recognized.
//
// Advances the current token position by yyleng columns without changing
// the line number.
# define YY_USER_ACTION context.current_token_position.columns(yyleng);
// the line number, and takes us out of the after-whitespace state.
# define YY_USER_ACTION \
context.current_token_position.columns(yyleng); \
if (YY_START == AFTER_WHITESPACE) BEGIN(INITIAL);
%}

%%
Expand Down Expand Up @@ -105,7 +110,6 @@ horizontal_whitespace [ \t\r]
"=" return yy::parser::make_EQUAL(context.current_token_position);
"-" return yy::parser::make_MINUS(context.current_token_position);
"+" return yy::parser::make_PLUS(context.current_token_position);
"*" return yy::parser::make_STAR(context.current_token_position);
"/" return yy::parser::make_SLASH(context.current_token_position);
"(" return yy::parser::make_LEFT_PARENTHESIS(context.current_token_position);
")" return yy::parser::make_RIGHT_PARENTHESIS(context.current_token_position);
Expand All @@ -118,6 +122,21 @@ horizontal_whitespace [ \t\r]
";" return yy::parser::make_SEMICOLON(context.current_token_position);
":" return yy::parser::make_COLON(context.current_token_position);

<INITIAL>"*" {
return yy::parser::make_UNARY_STAR(context.current_token_position);
}
<AFTER_WHITESPACE>"*" {
return yy::parser::make_PREFIX_STAR(context.current_token_position);
}
<INITIAL>"*"{whitespace}* {
BEGIN(AFTER_WHITESPACE);
return yy::parser::make_POSTFIX_STAR(context.current_token_position);
}
<AFTER_WHITESPACE>"*"{whitespace}* {
BEGIN(AFTER_WHITESPACE);
return yy::parser::make_BINARY_STAR(context.current_token_position);
}

{identifier} {
int n = strlen(yytext);
auto r = reinterpret_cast<char*>(malloc((n + 1) * sizeof(char)));
Expand All @@ -140,13 +159,15 @@ horizontal_whitespace [ \t\r]
{horizontal_whitespace}+ {
// Make the span empty by setting start to end.
context.current_token_position.step();
BEGIN(AFTER_WHITESPACE);
}

\n+ {
// Advance end by yyleng lines, resetting the column to zero.
context.current_token_position.lines(yyleng);
// Make the span empty by setting start to end.
context.current_token_position.step();
BEGIN(AFTER_WHITESPACE);
}

. {
Expand Down
19 changes: 17 additions & 2 deletions executable_semantics/syntax/parser.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ void yy::parser::error(
EQUAL "="
MINUS "-"
PLUS "+"
STAR "*"
UNARY_STAR "unary *"
PREFIX_STAR "prefix *"
POSTFIX_STAR "postfix *"
BINARY_STAR "binary *"
SLASH "/"
LEFT_PARENTHESIS "("
RIGHT_PARENTHESIS ")"
Expand All @@ -168,8 +171,10 @@ void yy::parser::error(
%precedence "," DBLARROW
%left OR AND
%nonassoc EQUAL_EQUAL
%left BINARY_STAR
%left "+" "-"
%precedence NOT UNARY_MINUS
%precedence NOT UNARY_MINUS PREFIX_STAR
%precedence POSTFIX_STAR UNARY_STAR
%left "." ARROW
%precedence "(" ")" "[" "]"

Expand All @@ -194,6 +199,8 @@ expression:
{ $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); }
| expression "-" expression
{ $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); }
| expression BINARY_STAR expression
{ $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Mul, $1, $3); }
| expression AND expression
{ $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); }
| expression OR expression
Expand All @@ -202,6 +209,10 @@ expression:
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Not, $2); }
| "-" expression %prec UNARY_MINUS
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); }
| PREFIX_STAR expression
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Deref, $2); }
| UNARY_STAR expression %prec PREFIX_STAR
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Deref, $2); }
| FNTY tuple return_type
{ $$ = Carbon::Expression::MakeFunType(yylineno, $2, $3); }
;
Expand Down Expand Up @@ -234,6 +245,10 @@ var_compatible_expression:
{ $$ = Carbon::Expression::MakeIndex(yylineno, $1, $3); }
| expression tuple
{ $$ = Carbon::Expression::MakeCall(yylineno, $1, $2); }
| expression POSTFIX_STAR
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Ptr, $1); }
| expression UNARY_STAR
{ $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Ptr, $1); }
;
designator: "." identifier { $$ = $2; }
;
Expand Down

0 comments on commit 16f10e3

Please sign in to comment.