mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 15:01:05 +01:00
Add string parsing and a print builtin (#721)
It was in my mind to add String in order to support libraries in `package`. `print` is added in order to have a String go to stdout. I've tried to do `print` in a way that won't be too hard to add other printable types, but it's probably also somewhat optional here -- that is, if desired, I could remove it. But it was a lot easier to doublecheck `\n` behavior with it, and I suspect it'll be helpful in other tests if it supports more value types. On the side, this also fixes dereferencing in Pattern/Expression Print() calls, which I was noticing printing pointers instead of values. This may be another argument for moving away from passing pointers, since this seems to be a difficult-to-catch error. Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
committed by
GitHub
co-authored by
Geoff Romer
parent
ecb5a611e5
commit
250ce4ab00
@@ -60,6 +60,15 @@ auto CurrentEnv(State* state) -> Env {
|
||||
return frame->scopes.Top()->values;
|
||||
}
|
||||
|
||||
// Returns the given name from the environment, printing an error if not found.
|
||||
static auto GetFromEnv(int line_num, const std::string& name) -> Address {
|
||||
std::optional<Address> pointer = CurrentEnv(state).Get(name);
|
||||
if (!pointer) {
|
||||
FATAL_RUNTIME_ERROR(line_num) << "could not find `" << name << "`";
|
||||
}
|
||||
return *pointer;
|
||||
}
|
||||
|
||||
void PrintState(llvm::raw_ostream& out) {
|
||||
out << "{\nstack: ";
|
||||
PrintStack(state->stack, out);
|
||||
@@ -411,14 +420,9 @@ void StepLvalue() {
|
||||
case Expression::Kind::IdentifierExpression: {
|
||||
// { {x :: C, E, F} :: S, H}
|
||||
// -> { {E(x) :: C, E, F} :: S, H}
|
||||
std::optional<Address> pointer =
|
||||
CurrentEnv(state).Get(cast<IdentifierExpression>(*exp).Name());
|
||||
if (!pointer) {
|
||||
FATAL_RUNTIME_ERROR(exp->LineNumber())
|
||||
<< "could not find `" << cast<IdentifierExpression>(*exp).Name()
|
||||
<< "`";
|
||||
}
|
||||
const Value* v = global_arena->New<PointerValue>(*pointer);
|
||||
Address pointer = GetFromEnv(exp->LineNumber(),
|
||||
cast<IdentifierExpression>(*exp).Name());
|
||||
const Value* v = global_arena->New<PointerValue>(pointer);
|
||||
frame->todo.Pop();
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
@@ -496,10 +500,12 @@ void StepLvalue() {
|
||||
case Expression::Kind::BoolTypeLiteral:
|
||||
case Expression::Kind::TypeTypeLiteral:
|
||||
case Expression::Kind::FunctionTypeLiteral:
|
||||
case Expression::Kind::ContinuationTypeLiteral: {
|
||||
case Expression::Kind::ContinuationTypeLiteral:
|
||||
case Expression::Kind::StringLiteral:
|
||||
case Expression::Kind::StringTypeLiteral:
|
||||
case Expression::Kind::IntrinsicExpression:
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "Can't treat expression as lvalue: " << *exp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -597,12 +603,8 @@ void StepExp() {
|
||||
CHECK(act->Pos() == 0);
|
||||
const auto& ident = cast<IdentifierExpression>(*exp);
|
||||
// { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H}
|
||||
std::optional<Address> pointer = CurrentEnv(state).Get(ident.Name());
|
||||
if (!pointer) {
|
||||
FATAL_RUNTIME_ERROR(exp->LineNumber())
|
||||
<< "could not find `" << ident.Name() << "`";
|
||||
}
|
||||
const Value* pointee = state->heap.Read(*pointer, exp->LineNumber());
|
||||
Address pointer = GetFromEnv(exp->LineNumber(), ident.Name());
|
||||
const Value* pointee = state->heap.Read(pointer, exp->LineNumber());
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(pointee));
|
||||
break;
|
||||
@@ -660,6 +662,22 @@ void StepExp() {
|
||||
FATAL() << "in handle_value with Call pos " << act->Pos();
|
||||
}
|
||||
break;
|
||||
case Expression::Kind::IntrinsicExpression:
|
||||
CHECK(act->Pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
frame->todo.Pop(1);
|
||||
switch (cast<IntrinsicExpression>(*exp).Intrinsic()) {
|
||||
case IntrinsicExpression::IntrinsicKind::Print:
|
||||
Address pointer = GetFromEnv(exp->LineNumber(), "format_str");
|
||||
const Value* pointee = state->heap.Read(pointer, exp->LineNumber());
|
||||
CHECK(pointee->Tag() == Value::Kind::StringValue);
|
||||
// TODO: This could eventually use something like llvm::formatv.
|
||||
llvm::outs() << cast<StringValue>(*pointee).Val();
|
||||
frame->todo.Push(global_arena->New<ValAction>(&TupleValue::Empty()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::Kind::IntTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<IntType>();
|
||||
@@ -710,6 +728,20 @@ void StepExp() {
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
case Expression::Kind::StringLiteral:
|
||||
CHECK(act->Pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(
|
||||
global_arena->New<StringValue>(cast<StringLiteral>(*exp).Val())));
|
||||
break;
|
||||
case Expression::Kind::StringTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<StringType>();
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
} // switch (exp->Tag)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user