7 #include "ast/ExprNode.h"
11 std::ostream&
Expr::print(std::ostream& os,
int indentation)
const {
12 if(indentation >= 0) {
18 for(
const auto op : rpn_ops.nodes()) {
19 if(indentation >= 0) {
20 std::ostringstream oss;
22 char cur = (oss.str().begin()[0] ==
'(') ?
'(' :
'.';
24 os << oss.str() <<
" ";
26 os <<
"\n" << AstNode::indent(indentation + 1) << oss.str() <<
" ";
34 if(indentation >= 0) {
40 int Expr::printDotNode(DotPrinter& dp)
const {
41 std::ostringstream os;
42 for(
const auto op : rpn_ops.nodes()) {
44 if(os.str().ends_with(
")")) {
54 void Expr::dump()
const {
this->print(std::cerr, 0); }
60 void ExprNode::dump()
const {
this->print(std::cerr) <<
"\n"; }
62 void ExprNodeList::dump()
const { print(std::cerr); }
64 std::ostream& ExprNodeList::print(std::ostream& os)
const {
65 for(
auto node : nodes()) {
73 void ExprNodeList::check_invariants()
const {
74 assert((!tail_ || tail_->next() ==
nullptr) &&
75 "Tail node should not have a next node");
76 assert(((head_ !=
nullptr) == (tail_ !=
nullptr)) &&
77 "Head is null if and only if tail is null");
78 assert(((head_ ==
nullptr) == (size_ == 0)) &&
79 "Size should be 0 if and only if head is null");
84 std::ostream&
MemberName::print(std::ostream& os)
const {
85 return os <<
"(MemberName " << name_ <<
")";
88 std::ostream&
MethodName::print(std::ostream& os)
const {
89 return os <<
"(MethodName " << name() <<
")";
92 std::ostream& ThisNode::print(std::ostream& os)
const {
return os <<
"(THIS)"; }
94 std::ostream& TypeNode::print(std::ostream& os)
const {
103 static uint8_t parseChar(std::string_view value) {
106 if(value.at(1) !=
'\\')
return (uint8_t)value.at(1);
108 if(isdigit(value.at(2))) {
110 uint8_t octal[3] = {0, 0, 0};
112 octal[0] = value.at(2) -
'0';
114 if(value.length() >= 4) octal[1] = value.at(3) -
'0';
116 if(value.length() >= 5) octal[2] = value.at(4) -
'0';
118 return (uint8_t)((octal[0] << 6) | (octal[1] << 3) | octal[2]);
121 switch(value.at(2)) {
139 assert(
false &&
"Invalid escape sequence");
143 static void unescapeString(std::string_view in, std::pmr::string& out) {
145 for(size_t i = 1; i < in.length(); i++) {
155 LiteralNode::LiteralNode(BumpAllocator& alloc, parsetree::
Literal const* node,
158 auto str = node->get_value();
161 if(type->isNumeric()) {
163 if(type->getKind() == ast::BuiltInType::Kind::Char) {
164 value = parseChar(str);
168 if(node->isNegative())
169 value = std::stoi(
"-" + std::string(str));
171 value = std::stoi(std::string(str));
172 }
catch(std::invalid_argument& e) {
173 assert(
false &&
"Invalid integer literal");
179 else if(type->isBoolean()) {
182 }
else if(str ==
"false") {
185 assert(
false &&
"Invalid boolean literal");
189 else if(type->isString()) {
191 value_ = std::pmr::string{alloc};
192 unescapeString(str, std::get<std::pmr::string>(value_));
195 else if(type->getKind() == ast::BuiltInType::Kind::NoneType) {
200 assert(
false &&
"Invalid type for literal node");
204 std::ostream& LiteralNode::print(std::ostream& os)
const {
207 builtinType()->print(os) <<
")";
211 ast::BuiltInType
const* LiteralNode::builtinType()
const {
212 return cast<ast::BuiltInType>(type());
215 std::ostream& MemberAccess::print(std::ostream& os)
const {
216 return os <<
"MemberAccess";
219 std::ostream& MethodInvocation::print(std::ostream& os)
const {
220 return os <<
"MethodInvocation(" << nargs() - 1 <<
")";
223 std::ostream& ClassInstanceCreation::print(std::ostream& os)
const {
224 return os <<
"(ClassInstanceCreation args: " << std::to_string(nargs()) <<
")";
227 std::ostream& ArrayInstanceCreation::print(std::ostream& os)
const {
228 return os <<
"ArrayInstanceCreation";
231 std::ostream& ArrayAccess::print(std::ostream& os)
const {
232 return os <<
"ArrayAccess";
235 std::ostream& Cast::print(std::ostream& os)
const {
return os <<
"Cast"; }
237 std::ostream& UnaryOp::print(std::ostream& os)
const {
238 return os << OpType_to_string(type,
"(Unknown unary op)");
241 std::ostream& BinaryOp::print(std::ostream& os)
const {
242 return os << OpType_to_string(type,
"(Unknown binary op)");