blob: 045df29d04c14de2787a1c8b5491fe1da82fa087 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_SHELL_INTERPRETER_SRC_EXPRESSIONS_H_
#define SRC_DEVELOPER_SHELL_INTERPRETER_SRC_EXPRESSIONS_H_
#include <cstdint>
#include <map>
#include <memory>
#include <string_view>
#include <utility>
#include <vector>
#include "src/developer/shell/interpreter/src/nodes.h"
#include "src/developer/shell/interpreter/src/types.h"
#include "src/developer/shell/interpreter/src/value.h"
namespace shell {
namespace interpreter {
// Defines an integer value.
class IntegerLiteral : public Expression {
public:
IntegerLiteral(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
uint64_t absolute_value, bool negative)
: Expression(interpreter, file_id, node_id),
absolute_value_(absolute_value),
negative_(negative) {}
uint64_t absolute_value() const { return absolute_value_; }
bool negative() const { return negative_; }
void Dump(std::ostream& os) const override;
bool IsConstant() const override { return true; }
std::unique_ptr<Type> InferType(ExecutionContext* context) const override;
bool Compile(ExecutionContext* context, code::Code* code, const Type* for_type) const override;
private:
// The absolute value for the integer.
const uint64_t absolute_value_;
// If true, this is a negative value (-absolute_value_).
const bool negative_;
};
// Fields of objects. Objects themselves are expressions.
// Located in this file for proximity to Objects.
class ObjectDeclarationField : public Node {
public:
ObjectDeclarationField(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
std::shared_ptr<ObjectFieldSchema> field_schema,
std::unique_ptr<Expression> value)
: Node(interpreter, file_id, node_id),
field_schema_(std::move(field_schema)),
expression_(std::move(value)) {}
// Prints the field.
void Dump(std::ostream& os) const;
const ObjectFieldSchema* schema() const { return field_schema_.get(); }
bool Compile(ExecutionContext* context, code::Code* code, const Type* for_type) {
return expression_->Compile(context, code, for_type);
}
private:
std::shared_ptr<ObjectFieldSchema> field_schema_;
std::unique_ptr<Expression> expression_;
};
inline std::ostream& operator<<(std::ostream& os, const ObjectDeclarationField& field) {
field.Dump(os);
return os;
}
// ObjectDeclarations are Objects (whether builtin or FIDL).
class ObjectDeclaration : public Expression {
public:
ObjectDeclaration(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
std::shared_ptr<ObjectSchema> object_schema,
std::vector<std::unique_ptr<ObjectDeclarationField>>&& fields);
const std::vector<std::unique_ptr<ObjectDeclarationField>>& fields() const { return fields_; }
// Prints the object.
virtual void Dump(std::ostream& os) const override;
std::unique_ptr<Type> InferType(ExecutionContext* context) const override;
// Compiles the instruction (performs the semantic checks and generates code).
virtual bool Compile(ExecutionContext* context, code::Code* code,
const Type* for_type) const override;
private:
std::shared_ptr<ObjectSchema> object_schema_;
// fields_ are stored in the same order the ObjectSchemaFields are found in the object_schema_.
std::vector<std::unique_ptr<ObjectDeclarationField>> fields_;
};
// Defines a string value.
class StringLiteral : public Expression {
public:
StringLiteral(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
std::string_view value)
: Expression(interpreter, file_id, node_id), string_(interpreter, value) {}
String* string() const { return string_.data(); }
void Dump(std::ostream& os) const override;
bool IsConstant() const override { return true; }
std::unique_ptr<Type> InferType(ExecutionContext* context) const override;
bool Compile(ExecutionContext* context, code::Code* code, const Type* for_type) const override;
private:
// The value for the string.
StringContainer string_;
};
class ExpressionVariable : public Expression {
public:
ExpressionVariable(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
std::string&& name)
: Expression(interpreter, file_id, node_id), name_(std::move(name)) {}
void Dump(std::ostream& os) const override;
std::unique_ptr<Type> InferType(ExecutionContext* context) const override;
bool Compile(ExecutionContext* context, code::Code* code, const Type* for_type) const override;
void Assign(ExecutionContext* context, code::Code* code) const override;
private:
const std::string name_;
};
class BinaryOperation : public Expression {
public:
BinaryOperation(Interpreter* interpreter, uint64_t file_id, uint64_t node_id,
std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: Expression(interpreter, file_id, node_id),
left_(std::move(left)),
right_(std::move(right)) {}
const Expression* left() const { return left_.get(); }
const Expression* right() const { return right_.get(); }
bool IsConstant() const override { return left_->IsConstant() && right_->IsConstant(); }
private:
std::unique_ptr<Expression> left_;
std::unique_ptr<Expression> right_;
};
class Addition : public BinaryOperation {
public:
Addition(Interpreter* interpreter, uint64_t file_id, uint64_t node_id, bool with_exceptions,
std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
: BinaryOperation(interpreter, file_id, node_id, std::move(left), std::move(right)),
with_exceptions_(with_exceptions) {}
bool with_exceptions() const { return with_exceptions_; }
void Dump(std::ostream& os) const override;
std::unique_ptr<Type> InferType(ExecutionContext* context) const override;
bool Compile(ExecutionContext* context, code::Code* code, const Type* for_type) const override;
size_t GenerateStringTerms(ExecutionContext* context, code::Code* code,
const Type* for_type) const override;
private:
bool with_exceptions_;
};
} // namespace interpreter
} // namespace shell
#endif // SRC_DEVELOPER_SHELL_INTERPRETER_SRC_EXPRESSIONS_H_