int OperationNode::Evaluate(const mtlChars &dst, mtlString &out, int lane, int depth) { int ldepth = left->Evaluate(dst, out, lane, depth); int rdepth = right->IsLeaf() ? 0 : right->Evaluate(dst, out, lane, depth+1); int mdepth = 0; mtlString addr_str; if (depth > 0 || dst.GetSize() == 0) { out.Append('['); addr_str.FromInt(depth); out.Append(addr_str); out.Append(']'); mdepth = depth; } else { mtlString temp; GetLane(dst, lane, temp); out.Append(temp); //out.Append(dst); } AppendValue(out); out.Append('='); if (right->IsLeaf()) { right->AppendValue(out); } else { addr_str.FromInt(depth+1); out.Append('['); out.Append(addr_str); out.Append(']'); } out.Append(';'); return mmlMax(ldepth, mdepth, rdepth); }
bool AssignVar(CompileInstance &inst, const mtlChars &name, const mtlChars &expr) { mtlChars base_name = GetBaseName(name); Definition *type = GetType(inst, base_name); if (type == NULL) { AddError(inst, "Undeclared variable", name); return false; } if (type->mut != Mutable) { AddError(inst, "Modifying a constant", name); return false; } ExpressionNode *tree = GenerateTree(expr); if (tree == NULL) { AddError(inst, "Malformed expression", expr); return false; } mtlChars base_mem = GetBaseMembers(name); bool result = true; Parser parser; mtlList<mtlChars> ops; mtlList<mtlChars> m; mtlString order_str; const int num_lanes = (base_mem.GetSize() > 0) ? base_mem.GetSize() : type->type.size; for (int lane = 0; lane < num_lanes; ++lane) { order_str.Free(); const int stack_size = tree->Evaluate(name, order_str, lane, 0); PushStack(inst, stack_size); order_str.SplitByChar(ops, ';'); mtlItem<mtlChars> *op = ops.GetFirst(); while (op != NULL && op->GetItem().GetSize() > 0) { parser.SetBuffer(op->GetItem()); switch (parser.MatchPart("%s+=%s%|%s-=%s%|%s*=%s%|%s/=%s%|%s=%s", m, NULL)) { case 0: EmitInstruction(inst, swsl::FLT_ADD_MM); break; case 1: EmitInstruction(inst, swsl::FLT_SUB_MM); break; case 2: EmitInstruction(inst, swsl::FLT_MUL_MM); break; case 3: EmitInstruction(inst, swsl::FLT_DIV_MM); break; case 4: EmitInstruction(inst, swsl::FLT_SET_MM); break; default: AddError(inst, "Invalid syntax", op->GetItem()); return false; break; } mtlItem<swsl::Instruction> *instr_item = inst.program.GetLast(); const mtlChars dst = m.GetFirst()->GetItem(); const mtlChars src = m.GetFirst()->GetNext()->GetItem(); EmitOperand(inst, dst); if (src.IsFloat()) { *((int*)(&instr_item->GetItem().instr)) += 1; } EmitOperand(inst, src); op = op->GetNext(); } PopStack(inst, stack_size); } delete tree; return result; }