예제 #1
0
 void *calc(int idx)
 {
     if (calcCurrent(idx)) {
         m_val = m_op.eval(*(Ti *)m_child->calc(idx));
     }
     return (void *)&m_val;
 }
예제 #2
0
 void *calc(int x, int y, int z, int w)
 {
     if (calcCurrent(x, y, z, w)) {
         m_val = m_op.eval(*(Ti *)m_child->calc(x, y, z, w));
     }
     return (void *)(&m_val);
 }
예제 #3
0
 void calc(int idx, int lim) final
 {
     m_op.eval(TNode<To>::m_val, m_child->m_val, lim);
 }
예제 #4
0
TypeInfo const* SecondPass::GetResultTypeOf(Expr* p, Symbol const* doNotUse = nullptr){
	NodeType nt = p->GetNodeType();

	switch (nt){
	case NodeType::IntLit:
	case NodeType::FloatLit:
	case NodeType::BoolLit:
	case NodeType::StringLit:
		return p->GetTypeInfo();
	case NodeType::Ident:
	{
							
		Ident* n = (Ident*)p;
		if (n->GetTypeInfo() == nullptr)
			return nullptr;
		if (n->GetSymbol()->type == Symbol::FUNCTION){
			AddError(n->GetToken(), "Symbol '%s' is a function, but used like a variable.", n->GetName().c_str());
			return nullptr;
		}
		if (doNotUse == nullptr) 
			return p->GetTypeInfo();
		else{
			
			if (n->GetSymbol() == doNotUse){
				AddError(n->GetToken(), "Symbol '%s' is used in its definition.", n->GetName().c_str());
				return nullptr;
			}
			return p->GetTypeInfo();
		}
	}

	case NodeType::UnOp:
	{
		UnOp* n = (UnOp*)p;
		UnOp::Types ntype = n->GetType();
		TypeInfo const* ti = GetResultTypeOf(n->GetExpr());

		if (ti == nullptr)
			return nullptr;

		if (ntype == UnOp::Neg && ti->name != "int" && ti->name != "float"){
			AddError(n->GetExpr()->GetToken(), "Type mismatch: Expected 'int' type but found '%s' in operation '%s'.", ti->name.c_str(), UnOp::GetTypeAsString(ntype));
			return nullptr;
		}
		if( ntype == UnOp::Not && ti->name != "bool" ){
			AddError(n->GetExpr()->GetToken(), "Type mismatch: Expected 'bool' type but found '%s' in operation '%s'.", ti->name.c_str(), UnOp::GetTypeAsString(ntype));
			return nullptr;
		}

		p->SetTypeInfo(m_typeTable.Get("bool"));
		return p->GetTypeInfo();
	}
	case NodeType::BinOp:
	{
		BinOp* n = (BinOp*) p;
		TypeInfo const* lt = GetResultTypeOf(n->GetLeft());
		TypeInfo const* rt = GetResultTypeOf(n->GetRight());

		if (lt == nullptr || rt == nullptr)
			return nullptr;

		switch (n->GetType()){
		case BinOp::Equal:
		case BinOp::Unequal:
			{
				if( lt != rt ){
					AddError(n->GetToken(), "Type mismatch: Expected same types but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(m_typeTable.Get("bool"));
				return p->GetTypeInfo();
			}
		case BinOp::LThan:
		case BinOp::LThanEq:
		case BinOp::GThan:
		case BinOp::GThanEq:
			{
				if( rt != lt || rt->name != "int" || rt->name != "float" ){
					AddError(n->GetToken(), "Type mismatch: Expected matching numeric types but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(m_typeTable.Get("bool"));
				return p->GetTypeInfo();
			}
		case BinOp::And:
		case BinOp::Or:
		case BinOp::Xor:
			{
				if( lt->name != "bool" || rt->name != "bool" ){
					AddError(n->GetToken(), "Type mismatch: Expected 'bool' types but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(m_typeTable.Get("bool"));
				return p->GetTypeInfo();
			}
		case BinOp::Sub:
		case BinOp::Mul:
		case BinOp::Div:
			{
				if( lt != rt || lt->name != "int" && lt->name != "float" ){
					AddError(n->GetToken(), "Type mismatch: Expected matching numeric types but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(lt);
				return p->GetTypeInfo();
			}
		case BinOp::Mod:
			{
				if (lt != rt || lt->name != "int"){
					AddError(n->GetToken(), "Type mismatch: Expected 'int' types but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(lt);
				return p->GetTypeInfo();
			}
		case BinOp::Add:
			{
				if (lt->name == "string" || rt->name == "string"){ //can concatenate strings with everything
					p->SetTypeInfo(m_typeTable.Get("string"));
					return p->GetTypeInfo();
				}
				if (lt != rt || lt->name != "int" && lt->name != "float"){
					AddError(n->GetToken(), "Type mismatch: Expected matching numeric types or strings but found '%s' and '%s' in operation '%s'.", lt->name.c_str(), rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}
				p->SetTypeInfo(lt);
				return p->GetTypeInfo();
			}
		case BinOp::Subscript:
		{
				if (!lt->isArray){
					AddError(n->GetRight()->GetToken(), "Type mismatch: Expected array type but found '%s' in operation '%s'.", rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}

				if (rt->name != "int"){
					AddError(n->GetRight()->GetToken(), "Type mismatch: Expected numeric type but found '%s' in operation '%s'.", rt->name.c_str(), BinOp::GetTypeAsString(n->GetType()));
					return nullptr;
				}

				auto simpleType = m_typeTable.Get(lt->GetSimpleTypeName());
				_ASSERT(simpleType != nullptr);

				p->SetTypeInfo(simpleType);
				return p->GetTypeInfo();
		}

		default:
			__debugbreak();
			return nullptr;
		}
	}

	case NodeType::FuncCallExpr:
	{
		FuncCallExpr* n = (FuncCallExpr*)p;
		
		Symbol const* calleeSym = n->GetCallee()->GetSymbol();
		
		TypeInfo const* calleeTI = p->GetTypeInfo(); // GetResultTypeOf(n->GetCallee());

		if (calleeSym->type != Symbol::FUNCTION){
			AddError(n->GetCallee()->GetToken(), "Symbol '%s' is not a function, but used as one.", calleeSym->name.c_str());
			return nullptr;
		}
		
		p->SetTypeInfo(calleeSym->GetTypeInfo());

		//check arguments
		const auto& args = n->GetArgs()->GetChildren();
		const auto& params = calleeSym->GetParamList()->GetChildren();

		if (args.size() != params.size()){
			AddError(n->GetCallee()->GetToken(), "Function requires %d arguments, but %d supplied.", params.size(), args.size());
			return p->GetTypeInfo();
		}

		for (size_t i = 0; i < args.size(); ++i){
			TypeInfo const* actual = GetResultTypeOf(args[i].get());
			TypeInfo const* required = params[i]->GetType()->GetTypeInfo();

			if (actual != required){
				AddError(args[i]->GetToken(), "%dth argument is type '%s' but must be of type '%s'.", i+1, required->name.c_str(), actual->name.c_str());
				//return p->GetTypeInfo();
			}
		}

		//All checked
		return p->GetTypeInfo();
	}
		
	default:
		__debugbreak();
		return nullptr;
	}
}