Exemple #1
0
void AsmStatement::toIR(IRState *irs)
{
    block *bpre;
    block *basm;
    Declaration *d;
    Symbol *s;
    Blockx *blx = irs->blx;

    //printf("AsmStatement::toIR(asmcode = %x)\n", asmcode);
    bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    basm = blx->curblock;
    list_append(&bpre->Bsucc, basm);
    basm->Bcode = asmcode;
    basm->Balign = asmalign;
#if 0
    if (label)
    {   block *b;

        b = labelToBlock(loc, blx, label);
        printf("AsmStatement::toIR() %p\n", b);
        if (b)
            list_append(&basm->Bsucc, b);
    }
#endif
    // Loop through each instruction, fixing Dsymbols into Symbol's
    for (code *c = asmcode; c; c = c->next)
    {   LabelDsymbol *label;
        block *b;

        switch (c->IFL1)
        {
        case FLblockoff:
        case FLblock:
            // FLblock and FLblockoff have LabelDsymbol's - convert to blocks
            label = c->IEVlsym1;
            b = labelToBlock(loc, blx, label);
            list_append(&basm->Bsucc, b);
            c->IEV1.Vblock = b;
            break;

        case FLdsymbol:
        case FLfunc:
            s = c->IEVdsym1->toSymbol();
            if (s->Sclass == SCauto && s->Ssymnum == -1)
                symbol_add(s);
            c->IEVsym1 = s;
            c->IFL1 = s->Sfl ? s->Sfl : FLauto;
            break;
        }

        // Repeat for second operand
        switch (c->IFL2)
        {
        case FLblockoff:
        case FLblock:
            label = c->IEVlsym2;
            b = labelToBlock(loc, blx, label);
            list_append(&basm->Bsucc, b);
            c->IEV2.Vblock = b;
            break;

        case FLdsymbol:
        case FLfunc:
            d = c->IEVdsym2;
            s = d->toSymbol();
            if (s->Sclass == SCauto && s->Ssymnum == -1)
                symbol_add(s);
            c->IEVsym2 = s;
            c->IFL2 = s->Sfl ? s->Sfl : FLauto;
            if (d->isDataseg())
                s->Sflags |= SFLlivexit;
            break;
        }
        //c->print();
    }

    basm->bIasmrefparam = refparam;             // are parameters reference?
    basm->usIasmregs = regs;                    // registers modified

    block_next(blx,BCasm, NULL);
    list_prepend(&basm->Bsucc, blx->curblock);

    if (naked)
    {
        blx->funcsym->Stype->Tty |= mTYnaked;
    }
}
Exemple #2
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement
    Scope sc_save;

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
        if (args)
        {
            for (size_t i = 0; i < args->dim; i++)
            {
                Expression *e = (*args)[i];

                e = e->semantic(sc);
                if (e->op != TOKerror && e->op != TOKtype)
                    e = e->ctfeInterpret();
                if (e->op == TOKerror)
                {   errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
                    return;
                }
                StringExp *se = e->toString();
                if (se)
                {
                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                }
                else
                    fprintf(stdmsg, "%s", e->toChars());
            }
            fprintf(stdmsg, "\n");
        }
        goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
        if (!args || args->dim != 1)
            error("string expected for library name");
        else
        {
            Expression *e = (*args)[0];

            e = e->semantic(sc);
            e = e->ctfeInterpret();
            (*args)[0] = e;
            if (e->op == TOKerror)
                goto Lnodecl;
            StringExp *se = e->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                char *name = (char *)mem.malloc(se->len + 1);
                memcpy(name, se->string, se->len);
                name[se->len] = 0;
                fprintf(stdmsg, "library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#ifdef IN_GCC
    else if (ident == Id::GNU_asm)
    {
        if (! args || args->dim != 2)
            error("identifier and string expected for asm name");
        else
        {
            Expression *e;
            Declaration *d = NULL;
            StringExp *s = NULL;

            e = (*args)[0];
            e = e->semantic(sc);
            if (e->op == TOKvar)
            {
                d = ((VarExp *)e)->var;
                if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
                    d = NULL;
            }
            if (!d)
                error("first argument of GNU_asm must be a function or variable declaration");

            e = (*args)[1];
            e = e->semantic(sc);
            e = e->ctfeInterpret();
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a character string");

            if (d && s)
                d->c_ident = Lexer::idPool((char*) s->string);
        }
        goto Lnodecl;
    }
    else if (ident == Id::GNU_attribute)
    {
        sc_save = *sc;

        // An empty list is allowed.
        if (args && args->dim)
        {
            Expressions * a;

            if (sc->attributes)
                a = (Expressions *) sc->attributes->copy();
            else
                a = new Expressions;
            sc->attributes = a;

            for (unsigned i = 0; i < args->dim; i++)
            {
                Expression * e = (*args)[i];
                //e = e->semantic(sc);

                if (e->op == TOKidentifier)
                    ; // ok
                else if (e->op == TOKcall)
                {
                    CallExp * c = (CallExp *) e;
                    if (c->e1->op != TOKidentifier)
                        error("identifier or call expression expected for attribute");
                    if (c->arguments)
                        for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
                        {
                            Expression * ea = c->arguments->tdata()[ai];
                            ea = ea->semantic(sc);
                            ea = ea->optimize(WANTvalue | WANTinterpret);
                            c->arguments->tdata()[ai] = ea;
                        }
                }
                else
                {
                    error("identifier or call expression expected for attribute");
                    continue;
                }
                a->push(e);
            }
        }
    }
    else if (ident == Id::GNU_set_attribute)
    {
        if (!args || args->dim < 1)
            error("declaration expected for setting attributes");
        else
        {
            Expressions ** p_attributes = NULL;     // list of existing attributes
            {
                Expression * e = (*args)[0];

                e = e->semantic(sc);
                if (e->op == TOKvar)
                {
                    Declaration * d = ((VarExp *)e)->var;
                    if (d->isFuncDeclaration() || d->isVarDeclaration())
                        p_attributes = & d->attributes;
                }
                else if (e->op == TOKtype)
                {
                    Type * t = ((TypeExp *)e)->type;
                    if (t->ty == Ttypedef)
                        p_attributes = & ((TypeTypedef *) t)->sym->attributes;
                    else if (t->ty == Tenum)
                        p_attributes = & ((TypeEnum *) t)->sym->attributes;
                    else if (t->ty == Tstruct)
                        p_attributes = & ((TypeStruct *) t)->sym->attributes;
                    else if (t->ty == Tclass)
                        p_attributes = & ((TypeClass *) t)->sym->attributes;
                }

                if (p_attributes == NULL)
                    error("first argument must be a function, variable, or type declaration");
            }

            Expressions * new_attrs = new Expressions;
            for (unsigned i = 1; i < args->dim; i++)
            {
                Expression * e = (*args)[i];
                //e = e->semantic(sc);

                if (e->op == TOKidentifier)
                    ; // ok
                else if (e->op == TOKcall)
                {
                    CallExp * c = (CallExp *) e;
                    if (c->e1->op != TOKidentifier)
                        error("identifier or call expression expected for attribute");
                    if (c->arguments)
                        for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
                        {
                            Expression * ea = c->arguments->tdata()[ai];
                            ea = ea->semantic(sc);
                            ea = ea->optimize(WANTvalue | WANTinterpret);
                            c->arguments->tdata()[ai] = ea;
                        }
                }
                else
                {
                    error("identifier or call expression expected for attribute");
                    continue;
                }
                new_attrs->push(e);
            }

            if (p_attributes)
            {
                if (*p_attributes)
                {
                    *p_attributes = (Expressions *) (*p_attributes)->copy();
                    (*p_attributes)->append(new_attrs);
                }
                else
                    *p_attributes = new_attrs;
            }
        }
        goto Lnodecl;
    }
#endif
#if DMDV2
    else if (ident == Id::startaddress)
    {
        if (!args || args->dim != 1)
            error("function name expected for start address");
        else
        {
            Expression *e = (*args)[0];
            e = e->semantic(sc);
            e = e->ctfeInterpret();
            (*args)[0] = e;
            Dsymbol *sa = getDsymbol(e);
            if (!sa || !sa->isFuncDeclaration())
                error("function name expected for start address, not '%s'", e->toChars());
        }
        goto Lnodecl;
    }
#endif
#if TARGET_NET
    else if (ident == Lexer::idPool("assembly"))
    {
    }
#endif // TARGET_NET
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            fprintf(stdmsg, "pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    Expression *e = (*args)[i];
                    e = e->semantic(sc);
                    e = e->ctfeInterpret();
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

Ldecl:
    if (decl)
    {
        for (size_t i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = (*decl)[i];

            s->semantic(sc);
        }
    }
#ifdef IN_GCC
    if (decl)
    {
        if (ident == Id::GNU_attribute)
            *sc = sc_save;
    }
#endif
    return;

Lnodecl:
    if (decl)
    {
        error("pragma is missing closing ';'");
        goto Ldecl; // do them anyway, to avoid segfaults.
    }
}
static bool
DeclareInner(Port &port, const Declaration &declaration,
             OperationEnvironment &env)
{
  assert(declaration.size() >= 2);
  assert(declaration.size() <= 12);

  char user_data[2500];

  if (!TryConnect(port, user_data) || env.IsCancelled())
    return false;

  char *p = strstr(user_data, "USER DETAILS");
  if (p != NULL)
    *p = 0;

  port.Write('\x18');         // start to upload file
  port.Write(user_data);

  port.Write("USER DETAILS\r\n--------------\r\n\r\n");
  EWMicroRecorderPrintf(port, _T("%-15s %s\r\n"),
                        _T("Pilot Name:"), declaration.PilotName.c_str());
  EWMicroRecorderPrintf(port, _T("%-15s %s\r\n"),
                        _T("Competition ID:"),
                        declaration.CompetitionId.c_str());
  EWMicroRecorderPrintf(port, _T("%-15s %s\r\n"),
                        _T("Aircraft Type:"),
                        declaration.AircraftType.c_str());
  EWMicroRecorderPrintf(port, _T("%-15s %s\r\n"),
                        _T("Aircraft ID:"), declaration.AircraftReg.c_str());
  port.Write("\r\nFLIGHT DECLARATION\r\n-------------------\r\n\r\n");

  EWMicroRecorderPrintf(port, _T("%-15s %s\r\n"),
                        _T("Description:"), _T("XCSoar task declaration"));

  for (unsigned i = 0; i < 11; i++) {
    if (env.IsCancelled())
      return false;

    if (i+1>= declaration.size()) {
      EWMicroRecorderPrintf(port, _T("%-17s %s\r\n"),
               _T("TP LatLon:"), _T("0000000N00000000E TURN POINT"));
    } else {
      const Waypoint &wp = declaration.get_waypoint(i);
      if (i == 0) {
        EWMicroRecorderWriteWaypoint(port, wp, _T("Take Off LatLong:"));
        EWMicroRecorderWriteWaypoint(port, wp, _T("Start LatLon:"));
      } else if (i + 1 < declaration.size()) {
        EWMicroRecorderWriteWaypoint(port, wp, _T("TP LatLon:"));
      }
    }
  }

  const Waypoint &wp = declaration.get_last_waypoint();
  EWMicroRecorderWriteWaypoint(port, wp, _T("Finish LatLon:"));
  EWMicroRecorderWriteWaypoint(port, wp, _T("Land LatLon:"));

  if (env.IsCancelled())
      return false;

  port.Write('\x03');         // finish sending user file

  return port.ExpectString("uploaded successfully");
}
Exemple #4
0
  void Output::operator()(Ruleset* r)
  {
    Selector* s     = r->selector();
    Block*    b     = r->block();
    bool      decls = false;

    // Filter out rulesets that aren't printable (process its children though)
    if (!Util::isPrintable(r, output_style())) {
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (dynamic_cast<Has_Block*>(stm)) {
          stm->perform(this);
        }
      }
      return;
    }

    if (b->has_non_hoistable()) {
      decls = true;
      if (output_style() == SASS_STYLE_NESTED) indentation += r->tabs();
      if (ctx && ctx->c_options->source_comments) {
        std::stringstream ss;
        append_indentation();
        ss << "/* line " << r->pstate().line + 1 << ", " << r->pstate().path << " */";
        append_string(ss.str());
        append_optional_linefeed();
      }
      s->perform(this);
      append_scope_opener(b);
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        bool bPrintExpression = true;
        // Check print conditions
        if (typeid(*stm) == typeid(Declaration)) {
          Declaration* dec = static_cast<Declaration*>(stm);
          if (dec->value()->concrete_type() == Expression::STRING) {
            String_Constant* valConst = static_cast<String_Constant*>(dec->value());
            std::string val(valConst->value());
            if (auto qstr = dynamic_cast<String_Quoted*>(valConst)) {
              if (!qstr->quote_mark() && val.empty()) {
                bPrintExpression = false;
              }
            }
          }
          else if (dec->value()->concrete_type() == Expression::LIST) {
            List* list = static_cast<List*>(dec->value());
            bool all_invisible = true;
            for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
              Expression* item = (*list)[list_i];
              if (!item->is_invisible()) all_invisible = false;
            }
            if (all_invisible) bPrintExpression = false;
          }
        }
        // Print if OK
        if (!stm->is_hoistable() && bPrintExpression) {
          stm->perform(this);
        }
      }
      if (output_style() == SASS_STYLE_NESTED) indentation -= r->tabs();
      append_scope_closer(b);
    }

    if (b->has_hoistable()) {
      if (decls) ++indentation;
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (stm->is_hoistable()) {
          stm->perform(this);
        }
      }
      if (decls) --indentation;
    }
  }
  void Output_Nested::operator()(Ruleset* r)
  {
    Selector* s     = r->selector();
    Block*    b     = r->block();
    bool      decls = false;

    if (s->has_placeholder()) return;

    if (b->has_non_hoistable()) {
      decls = true;
      indent();
      if (source_comments) {
        stringstream ss;
        ss << "/* line " << r->position().line << ", " << r->path() << " */" << endl;
        append_singleline_part_to_buffer(ss.str());
        indent();
      }
      s->perform(this);
      append_multiline_part_to_buffer(" {\n");
      ++indentation;
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        bool bPrintExpression = true;
        // Check print conditions
        if (typeid(*stm) == typeid(Declaration)) {
          Declaration* dec = static_cast<Declaration*>(stm);
          if (dec->value()->concrete_type() == Expression::STRING) {
            String_Constant* valConst = static_cast<String_Constant*>(dec->value());
            string val(valConst->value());
            if (val.empty()) {
              bPrintExpression = false;
            }
          }
          else if (dec->value()->concrete_type() == Expression::LIST) {
            List* list = static_cast<List*>(dec->value());
            bool all_invisible = true;
            for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
              Expression* item = (*list)[list_i];
              if (!item->is_invisible()) all_invisible = false;
            }
            if (all_invisible) bPrintExpression = false;
          }
        }
        // Print if OK
        if (!stm->is_hoistable() && bPrintExpression) {
          if (!stm->block()) indent();
          stm->perform(this);
          append_multiline_part_to_buffer("\n");
        }
      }
      --indentation;
      buffer.erase(buffer.length()-1);
      if (ctx) ctx->source_map.remove_line();
      append_multiline_part_to_buffer(" }\n");
    }

    if (b->has_hoistable()) {
      if (decls) ++indentation;
      // indent();
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (stm->is_hoistable()) {
          stm->perform(this);
        }
      }
      if (decls) --indentation;
    }
  }
Exemple #6
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
	if (args)
	{
	    for (size_t i = 0; i < args->dim; i++)
	    {
		Expression *e = (Expression *)args->data[i];

		e = e->semantic(sc);
		if (e->op == TOKstring)
		{
		    StringExp *se = (StringExp *)e;
		    fprintf(stdmsg, "%.*s", se->len, se->string);
		}
		else
		    error("string expected for message, not '%s'", e->toChars());
	    }
	    fprintf(stdmsg, "\n");
	}
	goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
	if (!args || args->dim != 1)
	    error("string expected for library name");
	else
	{
	    Expression *e = (Expression *)args->data[0];

	    e = e->semantic(sc);
	    args->data[0] = (void *)e;
	    if (e->op != TOKstring)
		error("string expected for library name, not '%s'", e->toChars());
	}
	goto Lnodecl;
    }
#if IN_GCC
    else if (ident == Id::GNU_asm)
    {
	if (! args || args->dim != 2)
	    error("identifier and string expected for asm name");
	else
	{
	    Expression *e;
	    Declaration *d = NULL;
	    StringExp *s = NULL;

	    e = (Expression *)args->data[0];
	    e = e->semantic(sc);
	    if (e->op == TOKvar)
	    {
		d = ((VarExp *)e)->var;
		if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
		    d = NULL;
	    }
	    if (!d)
		error("first argument of GNU_asm must be a function or variable declaration");

	    e = (Expression *)args->data[1];
	    e = e->semantic(sc);
	    e = e->optimize(WANTvalue);
	    if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
		s = ((StringExp *)e);
	    else
		error("second argument of GNU_asm must be a char string");

	    if (d && s)
		d->c_ident = Lexer::idPool((char*) s->string);
	}
	goto Lnodecl;
    }
#endif
    else
	error("unrecognized pragma(%s)", ident->toChars());

    if (decl)
    {
	for (unsigned i = 0; i < decl->dim; i++)
	{
	    Dsymbol *s = (Dsymbol *)decl->data[i];

	    s->semantic(sc);
	}
    }
    return;

Lnodecl:
    if (decl)
	error("pragma is missing closing ';'");
}
static bool
DeclareInner(Port &port, const Declaration &declaration,
             OperationEnvironment &env)
{
    assert(declaration.Size() >= 2);
    assert(declaration.Size() <= 12);

    char user_data[2500];

    if (!TryConnectRetry(port, user_data, sizeof(user_data), env))
        return false;

    char *p = strstr(user_data, "USER DETAILS");
    if (p != NULL)
        *p = 0;

    port.Write('\x18');         // start to upload file

    if (!port.FullWriteString(user_data, 5000) ||
            !port.FullWriteString("USER DETAILS\r\n--------------\r\n\r\n", 1000))
        return false;

    WritePair(port, "Pilot Name", declaration.pilot_name.c_str());
    WritePair(port, "Competition ID", declaration.competition_id.c_str());
    WritePair(port,  "Aircraft Type", declaration.aircraft_type.c_str());
    WritePair(port,  "Aircraft ID",
              declaration.aircraft_registration.c_str());

    if (!port.FullWriteString("\r\nFLIGHT DECLARATION\r\n-------------------\r\n\r\n",
                              1000))
        return false;

    WritePair(port, "Description", _T("XCSoar task declaration"));

    for (unsigned i = 0; i < 11; i++) {
        if (env.IsCancelled())
            return false;

        if (i+1>= declaration.Size()) {
            port.FullWriteString("TP LatLon: 0000000N00000000E TURN POINT\r\n",
                                 1000);
        } else {
            const Waypoint &wp = declaration.GetWaypoint(i);
            if (i == 0) {
                EWMicroRecorderWriteWaypoint(port, "Take Off LatLong", wp);
                EWMicroRecorderWriteWaypoint(port, "Start LatLon", wp);
            } else if (i + 1 < declaration.Size()) {
                EWMicroRecorderWriteWaypoint(port, "TP LatLon", wp);
            }
        }
    }

    const Waypoint &wp = declaration.GetLastWaypoint();
    EWMicroRecorderWriteWaypoint(port, "Finish LatLon", wp);
    EWMicroRecorderWriteWaypoint(port, "Land LatLon", wp);

    if (env.IsCancelled())
        return false;

    port.Write('\x03');         // finish sending user file

    return port.ExpectString("uploaded successfully");
}
Exemple #8
0
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{
    //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;

    // Look in symbols declared in this module
    Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
    if (s)
    {
        //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
    }
    else if (imports)
    {
        // Look in imported modules
        for (size_t i = 0; i < imports->dim; i++)
        {   ScopeDsymbol *ss = (*imports)[i];
            Dsymbol *s2;

            // If private import, don't search it
            if (flags & 1 && prots[i] == PROTprivate)
                continue;

            //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
            /* Don't find private members if ss is a module
             */
            s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
            if (!s)
                s = s2;
            else if (s2 && s != s2)
            {
                if (s->toAlias() == s2->toAlias())
                {
                    /* After following aliases, we found the same symbol,
                     * so it's not an ambiguity.
                     * But if one alias is deprecated, prefer the other.
                     */
                    if (s->isDeprecated())
                        s = s2;
                }
                else
                {
                    /* Two imports of the same module should be regarded as
                     * the same.
                     */
                    Import *i1 = s->isImport();
                    Import *i2 = s2->isImport();
                    if (!(i1 && i2 &&
                          (i1->mod == i2->mod ||
                           (!i1->parent->isImport() && !i2->parent->isImport() &&
                            i1->ident->equals(i2->ident))
                          )
                         )
                       )
                    {
                        ss->multiplyDefined(loc, s, s2);
                        break;
                    }
                }
            }
        }
        if (s)
        {
            Declaration *d = s->isDeclaration();
            if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin())
                error(loc, "%s is private", d->toPrettyChars());
        }
    }
    return s;
}
Exemple #9
0
static bool
DeclareInner(Port &port, const Declaration &declaration,
             gcc_unused OperationEnvironment &env)
{
  using CAI302::UploadShort;
  unsigned size = declaration.Size();

  port.SetRxTimeout(500);

  env.SetProgressRange(6 + size);
  env.SetProgressPosition(0);

  CAI302::CommandModeQuick(port);
  if (!CAI302::UploadMode(port) || env.IsCancelled())
    return false;

  port.SetRxTimeout(1500);

  CAI302::PilotMeta pilot_meta;
  if (!CAI302::UploadPilotMeta(port, pilot_meta) || env.IsCancelled())
    return false;

  env.SetProgressPosition(1);

  CAI302::Pilot pilot;
  if (!CAI302::UploadPilot(port, 0, pilot) || env.IsCancelled())
    return false;

  env.SetProgressPosition(2);

  CAI302::PolarMeta polar_meta;
  if (!CAI302::UploadPolarMeta(port, polar_meta) || env.IsCancelled())
    return false;

  env.SetProgressPosition(3);

  CAI302::Polar polar;
  if (!CAI302::UploadPolar(port, polar) || env.IsCancelled())
    return false;

  env.SetProgressPosition(4);

  if (!CAI302::DownloadMode(port) || env.IsCancelled())
    return false;

  char GliderType[13], GliderID[13];
  convert_string(GliderType, sizeof(GliderType), declaration.aircraft_type);
  convert_string(GliderID, sizeof(GliderID), declaration.aircraft_registration);

  convert_string(pilot.name, sizeof(pilot.name), declaration.pilot_name);
  if (!CAI302::DownloadPilot(port, pilot) || env.IsCancelled())
    return false;

  env.SetProgressPosition(5);

  convert_string(polar.glider_type, sizeof(polar.glider_type),
                 declaration.aircraft_type);
  convert_string(polar.glider_id, sizeof(polar.glider_id),
                 declaration.aircraft_registration);
  if (!CAI302::DownloadPolar(port, polar) || env.IsCancelled())
    return false;

  env.SetProgressPosition(6);

  for (unsigned i = 0; i < size; ++i) {
    if (!cai302DeclAddWaypoint(port, i, declaration.GetWaypoint(i)) ||
        env.IsCancelled())
      return false;

    env.SetProgressPosition(7 + i);
  }

  port.SetRxTimeout(1500); // D,255 takes more than 800ms
  return CAI302::DeclareSave(port);
}
Exemple #10
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
        if (args)
        {
            for (size_t i = 0; i < args->dim; i++)
            {
                Expression *e = args->tdata()[i];

                e = e->semantic(sc);
                e = e->optimize(WANTvalue | WANTinterpret);
                StringExp *se = e->toString();
                if (se)
                {
                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                }
                else
                    fprintf(stdmsg, "%s", e->toChars());
            }
            fprintf(stdmsg, "\n");
        }
        goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
        if (!args || args->dim != 1)
            error("string expected for library name");
        else
        {
            Expression *e = args->tdata()[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[0] = e;
            if (e->op == TOKerror)
                goto Lnodecl;
            StringExp *se = e->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                char *name = (char *)mem.malloc(se->len + 1);
                memcpy(name, se->string, se->len);
                name[se->len] = 0;
                printf("library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#if IN_GCC
    else if (ident == Id::GNU_asm)
    {
        if (! args || args->dim != 2)
            error("identifier and string expected for asm name");
        else
        {
            Expression *e;
            Declaration *d = NULL;
            StringExp *s = NULL;

            e = args->tdata()[0];
            e = e->semantic(sc);
            if (e->op == TOKvar)
            {
                d = ((VarExp *)e)->var;
                if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
                    d = NULL;
            }
            if (!d)
                error("first argument of GNU_asm must be a function or variable declaration");

            e = args->tdata()[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a char string");

            if (d && s)
                d->c_ident = Lexer::idPool((char*) s->string);
        }
        goto Lnodecl;
    }
#endif
#if DMDV2
    else if (ident == Id::startaddress)
    {
        if (!args || args->dim != 1)
            error("function name expected for start address");
        else
        {
            Expression *e = args->tdata()[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            args->tdata()[0] = e;
            Dsymbol *sa = getDsymbol(e);
            if (!sa || !sa->isFuncDeclaration())
                error("function name expected for start address, not '%s'", e->toChars());
        }
        goto Lnodecl;
    }
#endif
#if TARGET_NET
    else if (ident == Lexer::idPool("assembly"))
    {
    }
#endif // TARGET_NET
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            printf("pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    Expression *e = args->tdata()[i];
                    e = e->semantic(sc);
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
        goto Lnodecl;
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

    if (decl)
    {
        for (unsigned i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = decl->tdata()[i];

            s->semantic(sc);
        }
    }
    return;

Lnodecl:
    if (decl)
        error("pragma is missing closing ';'");
}
Exemple #11
0
void tst_Lookup::simple_class_1()
{
    const QByteArray source = "\n"
        "@interface Zoo {} +(id)alloc; -(id)init; @end\n"
        "@implementation Zoo +(id)alloc{} -(id)init{} -(void)dealloc{} @end\n";

    Document::Ptr doc = Document::create("simple_class_1");
    doc->setUtf8Source(source);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 2U);

    Snapshot snapshot;
    snapshot.insert(doc);

    ObjCClass *iface = doc->globalSymbolAt(0)->asObjCClass();
    QVERIFY(iface);
    QVERIFY(iface->isInterface());
    QCOMPARE(iface->memberCount(), 2U);

    ObjCClass *impl = doc->globalSymbolAt(1)->asObjCClass();
    QVERIFY(impl);
    QVERIFY(!impl->isInterface());
    QCOMPARE(impl->memberCount(), 3U);

    Declaration *allocMethodIface = iface->memberAt(0)->asDeclaration();
    QVERIFY(allocMethodIface);
    QVERIFY(allocMethodIface->name() && allocMethodIface->name()->identifier());
    QCOMPARE(QLatin1String(allocMethodIface->name()->identifier()->chars()), QLatin1String("alloc"));

    ObjCMethod *allocMethodImpl = impl->memberAt(0)->asObjCMethod();
    QVERIFY(allocMethodImpl);
    QVERIFY(allocMethodImpl->name() && allocMethodImpl->name()->identifier());
    QCOMPARE(QLatin1String(allocMethodImpl->name()->identifier()->chars()), QLatin1String("alloc"));

    ObjCMethod *deallocMethod = impl->memberAt(2)->asObjCMethod();
    QVERIFY(deallocMethod);
    QVERIFY(deallocMethod->name() && deallocMethod->name()->identifier());
    QCOMPARE(QLatin1String(deallocMethod->name()->identifier()->chars()), QLatin1String("dealloc"));

    const LookupContext context(doc, snapshot);

    // check class resolving:
    ClassOrNamespace *klass = context.lookupType(impl->name(), impl->enclosingScope());
    QVERIFY(klass != 0);
    QCOMPARE(klass->symbols().size(), 2);
    QVERIFY(klass->symbols().contains(iface));
    QVERIFY(klass->symbols().contains(impl));

    // check method resolving:
    QList<LookupItem> results = context.lookup(allocMethodImpl->name(), impl);
    QCOMPARE(results.size(), 2);
    QCOMPARE(results.at(0).declaration(), allocMethodIface);
    QCOMPARE(results.at(1).declaration(), allocMethodImpl);

    results = context.lookup(deallocMethod->name(), impl);
    QCOMPARE(results.size(), 1);
    QCOMPARE(results.at(0).declaration(), deallocMethod);
}
Exemple #12
0
Expression *TraitsExp::semantic(Scope *sc)
{
#if LOGSEMANTIC
    printf("TraitsExp::semantic() %s\n", toChars());
#endif
    if (ident != Id::compiles && ident != Id::isSame &&
        ident != Id::identifier)
    {
        TemplateInstance::semanticTiargs(loc, sc, args, 1);
    }
    size_t dim = args ? args->dim : 0;
    Object *o;
    Declaration *d;
    FuncDeclaration *f;

#define ISTYPE(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Type *t = getType((Object *)args->data[i]); \
            if (!t)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;

#define ISDSYMBOL(cond) \
        for (size_t i = 0; i < dim; i++)        \
        {   Dsymbol *s = getDsymbol((Object *)args->data[i]);   \
            if (!s)                             \
                goto Lfalse;                    \
            if (!(cond))                        \
                goto Lfalse;                    \
        }                                       \
        if (!dim)                               \
            goto Lfalse;                        \
        goto Ltrue;



    if (ident == Id::isArithmetic)
    {
        ISTYPE(t->isintegral() || t->isfloating())
    }
    else if (ident == Id::isFloating)
    {
        ISTYPE(t->isfloating())
    }
    else if (ident == Id::isIntegral)
    {
        ISTYPE(t->isintegral())
    }
    else if (ident == Id::isScalar)
    {
        ISTYPE(t->isscalar())
    }
    else if (ident == Id::isUnsigned)
    {
        ISTYPE(t->isunsigned())
    }
    else if (ident == Id::isAssociativeArray)
    {
        ISTYPE(t->toBasetype()->ty == Taarray)
    }
    else if (ident == Id::isStaticArray)
    {
        ISTYPE(t->toBasetype()->ty == Tsarray)
    }
    else if (ident == Id::isAbstractClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract())
    }
    else if (ident == Id::isFinalClass)
    {
        ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal)
    }
    else if (ident == Id::isAbstractFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract())
    }
    else if (ident == Id::isVirtualFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual())
    }
    else if (ident == Id::isFinalFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal())
    }
#if DMDV2
    else if (ident == Id::isStaticFunction)
    {
        ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && !f->needThis())
    }
    else if (ident == Id::isRef)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isRef())
    }
    else if (ident == Id::isOut)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->isOut())
    }
    else if (ident == Id::isLazy)
    {
        ISDSYMBOL((d = s->isDeclaration()) != NULL && d->storage_class & STClazy)
    }
    else if (ident == Id::identifier)
    {   // Get identifier for symbol as a string literal

        // Specify 0 for the flags argument to semanticTiargs() so that
        // a symbol should not be folded to a constant.
        TemplateInstance::semanticTiargs(loc, sc, args, 0);

        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        if (!s || !s->ident)
        {
            error("argument %s has no identifier", o->toChars());
            goto Lfalse;
        }
        StringExp *se = new StringExp(loc, s->ident->toChars());
        return se->semantic(sc);
    }
    else if (ident == Id::parent)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        if (s)
            s = s->toParent();
        if (!s)
        {
            error("argument %s has no parent", o->toChars());
            goto Lfalse;
        }
        return (new DsymbolExp(loc, s))->semantic(sc);
    }

#endif
    else if (ident == Id::hasMember ||
             ident == Id::getMember ||
             ident == Id::getOverloads ||
             ident == Id::getVirtualFunctions)
    {
        if (dim != 2)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Expression *e = isExpression((Object *)args->data[1]);
        if (!e)
        {   error("expression expected as second argument of __traits %s", ident->toChars());
            goto Lfalse;
        }
        e = e->optimize(WANTvalue | WANTinterpret);
        if (e->op != TOKstring)
        {   error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars());
            goto Lfalse;
        }
        StringExp *se = (StringExp *)e;
        se = se->toUTF8(sc);
        if (se->sz != 1)
        {   error("string must be chars");
            goto Lfalse;
        }
        Identifier *id = Lexer::idPool((char *)se->string);

        Type *t = isType(o);
        e = isExpression(o);
        Dsymbol *s = isDsymbol(o);
        if (t)
            e = typeDotIdExp(loc, t, id);
        else if (e)
            e = new DotIdExp(loc, e, id);
        else if (s)
        {   e = new DsymbolExp(loc, s);
            e = new DotIdExp(loc, e, id);
        }
        else
        {   error("invalid first argument");
            goto Lfalse;
        }

        if (ident == Id::hasMember)
        {   /* Take any errors as meaning it wasn't found
             */
            e = e->trySemantic(sc);
            if (!e)
            {   if (global.gag)
                    global.errors++;
                goto Lfalse;
            }
            else
                goto Ltrue;
        }
        else if (ident == Id::getMember)
        {
            e = e->semantic(sc);
            return e;
        }
        else if (ident == Id::getVirtualFunctions ||
                 ident == Id::getOverloads)
        {
            unsigned errors = global.errors;
            Expression *ex = e;
            e = e->semantic(sc);
            if (errors < global.errors)
                error("%s cannot be resolved", ex->toChars());

            /* Create tuple of functions of e
             */
            //e->dump(0);
            Expressions *exps = new Expressions();
            FuncDeclaration *f;
            if (e->op == TOKvar)
            {   VarExp *ve = (VarExp *)e;
                f = ve->var->isFuncDeclaration();
            }
            else if (e->op == TOKdotvar)
            {   DotVarExp *dve = (DotVarExp *)e;
                f = dve->var->isFuncDeclaration();
            }
            else
                f = NULL;
            Ptrait p;
            p.exps = exps;
            p.e1 = e;
            p.ident = ident;
            overloadApply(f, fptraits, &p);

            TupleExp *tup = new TupleExp(loc, exps);
            return tup->semantic(sc);
        }
        else
            assert(0);
    }
    else if (ident == Id::classInstanceSize)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ClassDeclaration *cd;
        if (!s || (cd = s->isClassDeclaration()) == NULL)
        {
            error("first argument is not a class");
            goto Lfalse;
        }
        return new IntegerExp(loc, cd->structsize, Type::tsize_t);
    }
    else if (ident == Id::allMembers || ident == Id::derivedMembers)
    {
        if (dim != 1)
            goto Ldimerror;
        Object *o = (Object *)args->data[0];
        Dsymbol *s = getDsymbol(o);
        ScopeDsymbol *sd;
        if (!s)
        {
            error("argument has no members");
            goto Lfalse;
        }
        if ((sd = s->isScopeDsymbol()) == NULL)
        {
            error("%s %s has no members", s->kind(), s->toChars());
            goto Lfalse;
        }
        Expressions *exps = new Expressions;
        while (1)
        {   size_t dim = ScopeDsymbol::dim(sd->members);
            for (size_t i = 0; i < dim; i++)
            {
                Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i);
                //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars());
                if (sm->ident)
                {
                    //printf("\t%s\n", sm->ident->toChars());
                    char *str = sm->ident->toChars();

                    /* Skip if already present in exps[]
                     */
                    for (size_t j = 0; j < exps->dim; j++)
                    {   StringExp *se2 = (StringExp *)exps->data[j];
                        if (strcmp(str, (char *)se2->string) == 0)
                            goto Lnext;
                    }

                    StringExp *se = new StringExp(loc, str);
                    exps->push(se);
                }
            Lnext:
                ;
            }
            ClassDeclaration *cd = sd->isClassDeclaration();
            if (cd && cd->baseClass && ident == Id::allMembers)
                sd = cd->baseClass;     // do again with base class
            else
                break;
        }
#if DMDV1
        Expression *e = new ArrayLiteralExp(loc, exps);
#endif
#if DMDV2
        /* Making this a tuple is more flexible, as it can be statically unrolled.
         * To make an array literal, enclose __traits in [ ]:
         *   [ __traits(allMembers, ...) ]
         */
        Expression *e = new TupleExp(loc, exps);
#endif
        e = e->semantic(sc);
        return e;
    }
    else if (ident == Id::compiles)
    {
        /* Determine if all the objects - types, expressions, or symbols -
         * compile without error
         */
        if (!dim)
            goto Lfalse;

        for (size_t i = 0; i < dim; i++)
        {   Object *o = (Object *)args->data[i];
            Expression *e;

            unsigned errors = global.errors;
            global.gag++;

            Type *t = isType(o);
            if (t)
            {   Dsymbol *s;
                t->resolve(loc, sc, &e, &t, &s);
                if (t)
                    t->semantic(loc, sc);
                else if (e)
                {   e = e->semantic(sc);
                    e = e->optimize(WANTvalue);
                }
            }
            else
            {   e = isExpression(o);
                if (e)
                {   e = e->semantic(sc);
                    e = e->optimize(WANTvalue);
                }
            }

            global.gag--;
            if (errors != global.errors)
            {
                global.errors = errors;
                goto Lfalse;
            }
        }
        goto Ltrue;
    }
    else if (ident == Id::isSame)
    {   /* Determine if two symbols are the same
         */
        if (dim != 2)
            goto Ldimerror;
        TemplateInstance::semanticTiargs(loc, sc, args, 0);
        Object *o1 = (Object *)args->data[0];
        Object *o2 = (Object *)args->data[1];
        Dsymbol *s1 = getDsymbol(o1);
        Dsymbol *s2 = getDsymbol(o2);

        //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars());
#if 0
        printf("o1: %p\n", o1);
        printf("o2: %p\n", o2);
        if (!s1)
        {   Expression *ea = isExpression(o1);
            if (ea)
                printf("%s\n", ea->toChars());
            Type *ta = isType(o1);
            if (ta)
                printf("%s\n", ta->toChars());
            goto Lfalse;
        }
        else
            printf("%s %s\n", s1->kind(), s1->toChars());
#endif
        if (!s1 && !s2)
        {   Expression *ea1 = isExpression(o1);
            Expression *ea2 = isExpression(o2);
            if (ea1 && ea2)
            {
                if (ea1->equals(ea2))
                    goto Ltrue;
            }
        }

        if (!s1 || !s2)
            goto Lfalse;

        s1 = s1->toAlias();
        s2 = s2->toAlias();

        if (s1 == s2)
            goto Ltrue;
        else
            goto Lfalse;
    }
    else
    {   error("unrecognized trait %s", ident->toChars());
        goto Lfalse;
    }

    return NULL;

Lnottype:
    error("%s is not a type", o->toChars());
    goto Lfalse;

Ldimerror:
    error("wrong number of arguments %d", dim);
    goto Lfalse;


Lfalse:
    return new IntegerExp(loc, 0, Type::tbool);

Ltrue:
    return new IntegerExp(loc, 1, Type::tbool);
}
Exemple #13
0
  void Output_Nested::operator()(Ruleset* r)
  {
    Selector* s     = r->selector();
    Block*    b     = r->block();
    bool      decls = false;

    // In case the extend visitor isn't called (if there are no @extend
    // directives in the entire document), check for placeholders here and
    // make sure they aren't output.
    // TODO: investigate why I decided to duplicate this logic in the extend visitor
    Selector_List* sl = static_cast<Selector_List*>(s);
    if (!ctx->extensions.size()) {
      Selector_List* new_sl = new (ctx->mem) Selector_List(sl->path(), sl->position());
      for (size_t i = 0, L = sl->length(); i < L; ++i) {
        if (!(*sl)[i]->has_placeholder()) {
          *new_sl << (*sl)[i];
        }
      }
      s = new_sl;
      sl = new_sl;
      r->selector(new_sl);
    }

    if (sl->length() == 0) return;

    if (b->has_non_hoistable()) {
      decls = true;
      indent();
      if (source_comments) {
        stringstream ss;
        ss << "/* line " << r->position().line << ", " << r->path() << " */" << endl;
        append_singleline_part_to_buffer(ss.str());
        indent();
      }
      s->perform(this);
      append_multiline_part_to_buffer(" {\n");
      ++indentation;
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        bool bPrintExpression = true;
        // Check print conditions
        if (typeid(*stm) == typeid(Declaration)) {
          Declaration* dec = static_cast<Declaration*>(stm);
          if (dec->value()->concrete_type() == Expression::STRING) {
            String_Constant* valConst = static_cast<String_Constant*>(dec->value());
            string val(valConst->value());
            if (val.empty()) {
              bPrintExpression = false;
            }
          }
          else if (dec->value()->concrete_type() == Expression::LIST) {
            List* list = static_cast<List*>(dec->value());
            bool all_invisible = true;
            for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
              Expression* item = (*list)[list_i];
              if (!item->is_invisible()) all_invisible = false;
            }
            if (all_invisible) bPrintExpression = false;
          }
        }
        // Print if OK
        if (!stm->is_hoistable() && bPrintExpression) {
          if (!stm->block()) indent();
          stm->perform(this);
          append_multiline_part_to_buffer("\n");
        }
      }
      --indentation;
      buffer.erase(buffer.length()-1);
      if (ctx) ctx->source_map.remove_line();
      append_multiline_part_to_buffer(" }\n");
    }

    if (b->has_hoistable()) {
      if (decls) ++indentation;
      // indent();
      for (size_t i = 0, L = b->length(); i < L; ++i) {
        Statement* stm = (*b)[i];
        if (stm->is_hoistable()) {
          stm->perform(this);
        }
      }
      if (decls) --indentation;
    }
  }
Exemple #14
0
inline void debug_ast(AST_Node* node, std::string ind, Env* env)
{
  if (node == 0) return;
  if (ind == "") std::cerr << "####################################################################\n";
  if (dynamic_cast<Bubble*>(node)) {
    Bubble* bubble = dynamic_cast<Bubble*>(node);
    std::cerr << ind << "Bubble " << bubble;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << bubble->tabs();
    std::cerr << std::endl;
    debug_ast(bubble->node(), ind + " ", env);
  } else if (dynamic_cast<Trace*>(node)) {
    Trace* trace = dynamic_cast<Trace*>(node);
    std::cerr << ind << "Trace " << trace;
    std::cerr << " (" << pstate_source_position(node) << ")"
    << " [name:" << trace->name() << "]"
    << std::endl;
    debug_ast(trace->block(), ind + " ", env);
  } else if (dynamic_cast<At_Root_Block*>(node)) {
    At_Root_Block* root_block = dynamic_cast<At_Root_Block*>(node);
    std::cerr << ind << "At_Root_Block " << root_block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << root_block->tabs();
    std::cerr << std::endl;
    debug_ast(root_block->expression(), ind + ":", env);
    debug_ast(root_block->block(), ind + " ", env);
  } else if (dynamic_cast<CommaSequence_Selector*>(node)) {
    CommaSequence_Selector* selector = dynamic_cast<CommaSequence_Selector*>(node);
    std::cerr << ind << "CommaSequence_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " [@media:" << selector->media_block() << "]";
    std::cerr << (selector->is_invisible() ? " [INVISIBLE]": " -");
    std::cerr << (selector->has_placeholder() ? " [PLACEHOLDER]": " -");
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;

    for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }

//  } else if (dynamic_cast<Expression*>(node)) {
//    Expression* expression = dynamic_cast<Expression*>(node);
//    std::cerr << ind << "Expression " << expression << " " << expression->concrete_type() << std::endl;

  } else if (dynamic_cast<Parent_Selector*>(node)) {
    Parent_Selector* selector = dynamic_cast<Parent_Selector*>(node);
    std::cerr << ind << "Parent_Selector " << selector;
//    if (selector->not_selector()) cerr << " [in_declaration]";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " [" << (selector->is_real_parent_ref() ? "REAL" : "FAKE") << "]";
    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl;
//    debug_ast(selector->selector(), ind + "->", env);

  } else if (dynamic_cast<Sequence_Selector*>(node)) {
    Sequence_Selector* selector = dynamic_cast<Sequence_Selector*>(node);
    std::cerr << ind << "Sequence_Selector " << selector
      << " (" << pstate_source_position(node) << ")"
      << " <" << selector->hash() << ">"
      << " [length:" << longToHex(selector->length()) << "]"
      << " [weight:" << longToHex(selector->specificity()) << "]"
      << " [@media:" << selector->media_block() << "]"
      << (selector->is_invisible() ? " [INVISIBLE]": " -")
      << (selector->has_placeholder() ? " [PLACEHOLDER]": " -")
      << (selector->is_optional() ? " [is_optional]": " -")
      << (selector->has_parent_ref() ? " [has parent]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
      << (selector->has_line_break() ? " [line-break]": " -")
      << " -- ";
      std::string del;
      switch (selector->combinator()) {
        case Sequence_Selector::PARENT_OF:   del = ">"; break;
        case Sequence_Selector::PRECEDES:    del = "~"; break;
        case Sequence_Selector::ADJACENT_TO: del = "+"; break;
        case Sequence_Selector::ANCESTOR_OF: del = " "; break;
        case Sequence_Selector::REFERENCE:   del = "//"; break;
      }
      // if (del = "/") del += selector->reference()->perform(&to_string) + "/";
    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl;
    debug_ast(selector->head(), ind + " " /* + "[" + del + "]" */, env);
    if (selector->tail()) {
      debug_ast(selector->tail(), ind + "{" + del + "}", env);
    } else if(del != " ") {
      std::cerr << ind << " |" << del << "| {trailing op}" << std::endl;
    }
    SourcesSet set = selector->sources();
    // debug_sources_set(set, ind + "  @--> ");
  } else if (dynamic_cast<SimpleSequence_Selector*>(node)) {
    SimpleSequence_Selector* selector = dynamic_cast<SimpleSequence_Selector*>(node);
    std::cerr << ind << "SimpleSequence_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " [weight:" << longToHex(selector->specificity()) << "]";
    std::cerr << " [@media:" << selector->media_block() << "]";
    std::cerr << (selector->extended() ? " [extended]": " -");
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl;
    for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Wrapped_Selector*>(node)) {
    Wrapped_Selector* selector = dynamic_cast<Wrapped_Selector*>(node);
    std::cerr << ind << "Wrapped_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;
    debug_ast(selector->selector(), ind + " () ", env);
  } else if (dynamic_cast<Pseudo_Selector*>(node)) {
    Pseudo_Selector* selector = dynamic_cast<Pseudo_Selector*>(node);
    std::cerr << ind << "Pseudo_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;
    debug_ast(selector->expression(), ind + " <= ", env);
  } else if (dynamic_cast<Attribute_Selector*>(node)) {
    Attribute_Selector* selector = dynamic_cast<Attribute_Selector*>(node);
    std::cerr << ind << "Attribute_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;
    debug_ast(selector->value(), ind + "[" + selector->matcher() + "] ", env);
  } else if (dynamic_cast<Class_Selector*>(node)) {
    Class_Selector* selector = dynamic_cast<Class_Selector*>(node);
    std::cerr << ind << "Class_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;
  } else if (dynamic_cast<Id_Selector*>(node)) {
    Id_Selector* selector = dynamic_cast<Id_Selector*>(node);
    std::cerr << ind << "Id_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << std::endl;
  } else if (dynamic_cast<Element_Selector*>(node)) {
    Element_Selector* selector = dynamic_cast<Element_Selector*>(node);
    std::cerr << ind << "Element_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <" << selector->hash() << ">";
    std::cerr << " <<" << selector->ns_name() << ">>";
    std::cerr << (selector->is_optional() ? " [is_optional]": " -");
    std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -");
    std::cerr << (selector->has_line_break() ? " [line-break]": " -");
    std::cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">";
    std::cerr << std::endl;
  } else if (dynamic_cast<Placeholder_Selector*>(node)) {

    Placeholder_Selector* selector = dynamic_cast<Placeholder_Selector*>(node);
    std::cerr << ind << "Placeholder_Selector [" << selector->ns_name() << "] " << selector
      << " <" << selector->hash() << ">"
      << " [@media:" << selector->media_block() << "]"
      << (selector->is_optional() ? " [is_optional]": " -")
      << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << std::endl;

  } else if (dynamic_cast<Simple_Selector*>(node)) {
    Simple_Selector* selector = dynamic_cast<Simple_Selector*>(node);
    std::cerr << ind << "Simple_Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl;

  } else if (dynamic_cast<Selector_Schema*>(node)) {
    Selector_Schema* selector = dynamic_cast<Selector_Schema*>(node);
    std::cerr << ind << "Selector_Schema " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")"
      << (selector->at_root() && selector->at_root() ? " [@ROOT]" : "")
      << " [@media:" << selector->media_block() << "]"
      << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << std::endl;

    debug_ast(selector->contents(), ind + " ");
    // for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }

  } else if (dynamic_cast<Selector*>(node)) {
    Selector* selector = dynamic_cast<Selector*>(node);
    std::cerr << ind << "Selector " << selector;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << std::endl;

  } else if (dynamic_cast<Media_Query_Expression*>(node)) {
    Media_Query_Expression* block = dynamic_cast<Media_Query_Expression*>(node);
    std::cerr << ind << "Media_Query_Expression " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << (block->is_interpolated() ? " [is_interpolated]": " -")
    << std::endl;
    debug_ast(block->feature(), ind + " feature) ");
    debug_ast(block->value(), ind + " value) ");

  } else if (dynamic_cast<Media_Query*>(node)) {
    Media_Query* block = dynamic_cast<Media_Query*>(node);
    std::cerr << ind << "Media_Query " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << (block->is_negated() ? " [is_negated]": " -")
      << (block->is_restricted() ? " [is_restricted]": " -")
    << std::endl;
    debug_ast(block->media_type(), ind + " ");
    for(auto i : block->elements()) { debug_ast(i, ind + " ", env); }

  } else if (dynamic_cast<Media_Block*>(node)) {
    Media_Block* block = dynamic_cast<Media_Block*>(node);
    std::cerr << ind << "Media_Block " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->media_queries(), ind + " =@ ");
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Supports_Block*>(node)) {
    Supports_Block* block = dynamic_cast<Supports_Block*>(node);
    std::cerr << ind << "Supports_Block " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->condition(), ind + " =@ ");
    debug_ast(block->block(), ind + " <>");
  } else if (dynamic_cast<Supports_Operator*>(node)) {
    Supports_Operator* block = dynamic_cast<Supports_Operator*>(node);
    std::cerr << ind << "Supports_Operator " << block;
    std::cerr << " (" << pstate_source_position(node) << ")"
    << std::endl;
    debug_ast(block->left(), ind + " left) ");
    debug_ast(block->right(), ind + " right) ");
  } else if (dynamic_cast<Supports_Negation*>(node)) {
    Supports_Negation* block = dynamic_cast<Supports_Negation*>(node);
    std::cerr << ind << "Supports_Negation " << block;
    std::cerr << " (" << pstate_source_position(node) << ")"
    << std::endl;
    debug_ast(block->condition(), ind + " condition) ");
  } else if (dynamic_cast<At_Root_Query*>(node)) {
    At_Root_Query* block = dynamic_cast<At_Root_Query*>(node);
    std::cerr << ind << "At_Root_Query " << block;
    std::cerr << " (" << pstate_source_position(node) << ")"
    << std::endl;
    debug_ast(block->feature(), ind + " feature) ");
    debug_ast(block->value(), ind + " value) ");
  } else if (dynamic_cast<Supports_Declaration*>(node)) {
    Supports_Declaration* block = dynamic_cast<Supports_Declaration*>(node);
    std::cerr << ind << "Supports_Declaration " << block;
    std::cerr << " (" << pstate_source_position(node) << ")"
    << std::endl;
    debug_ast(block->feature(), ind + " feature) ");
    debug_ast(block->value(), ind + " value) ");
  } else if (dynamic_cast<Block*>(node)) {
    Block* root_block = dynamic_cast<Block*>(node);
    std::cerr << ind << "Block " << root_block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    if (root_block->is_root()) std::cerr << " [root]";
    std::cerr << " " << root_block->tabs() << std::endl;
    if (root_block->block()) for(auto i : root_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Warning*>(node)) {
    Warning* block = dynamic_cast<Warning*>(node);
    std::cerr << ind << "Warning " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->message(), ind + " : ");
  } else if (dynamic_cast<Error*>(node)) {
    Error* block = dynamic_cast<Error*>(node);
    std::cerr << ind << "Error " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
  } else if (dynamic_cast<Debug*>(node)) {
    Debug* block = dynamic_cast<Debug*>(node);
    std::cerr << ind << "Debug " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->value(), ind + " ");
  } else if (dynamic_cast<Comment*>(node)) {
    Comment* block = dynamic_cast<Comment*>(node);
    std::cerr << ind << "Comment " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() <<
      " <" << prettyprint(block->pstate().token.ws_before()) << ">" << std::endl;
    debug_ast(block->text(), ind + "// ", env);
  } else if (dynamic_cast<If*>(node)) {
    If* block = dynamic_cast<If*>(node);
    std::cerr << ind << "If " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->predicate(), ind + " = ");
    debug_ast(block->block(), ind + " <>");
    debug_ast(block->alternative(), ind + " ><");
  } else if (dynamic_cast<Return*>(node)) {
    Return* block = dynamic_cast<Return*>(node);
    std::cerr << ind << "Return " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
  } else if (dynamic_cast<Extension*>(node)) {
    Extension* block = dynamic_cast<Extension*>(node);
    std::cerr << ind << "Extension " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->selector(), ind + "-> ", env);
  } else if (dynamic_cast<Content*>(node)) {
    Content* block = dynamic_cast<Content*>(node);
    std::cerr << ind << "Content " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [@media:" << block->media_block() << "]";
    std::cerr << " " << block->tabs() << std::endl;
  } else if (dynamic_cast<Import_Stub*>(node)) {
    Import_Stub* block = dynamic_cast<Import_Stub*>(node);
    std::cerr << ind << "Import_Stub " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << block->imp_path() << "] ";
    std::cerr << " " << block->tabs() << std::endl;
  } else if (dynamic_cast<Import*>(node)) {
    Import* block = dynamic_cast<Import*>(node);
    std::cerr << ind << "Import " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    // std::vector<std::string>         files_;
    for (auto imp : block->urls()) debug_ast(imp, ind + "@: ", env);
    debug_ast(block->media_queries(), ind + "@@ ");
  } else if (dynamic_cast<Assignment*>(node)) {
    Assignment* block = dynamic_cast<Assignment*>(node);
    std::cerr << ind << "Assignment " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " <<" << block->variable() << ">> " << block->tabs() << std::endl;
    debug_ast(block->value(), ind + "=", env);
  } else if (dynamic_cast<Declaration*>(node)) {
    Declaration* block = dynamic_cast<Declaration*>(node);
    std::cerr << ind << "Declaration " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->property(), ind + " prop: ", env);
    debug_ast(block->value(), ind + " value: ", env);
    debug_ast(block->block(), ind + " ", env);
  } else if (dynamic_cast<Keyframe_Rule*>(node)) {
    Keyframe_Rule* has_block = dynamic_cast<Keyframe_Rule*>(node);
    std::cerr << ind << "Keyframe_Rule " << has_block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << has_block->tabs() << std::endl;
    if (has_block->selector()) debug_ast(has_block->selector(), ind + "@");
    if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Directive*>(node)) {
    Directive* block = dynamic_cast<Directive*>(node);
    std::cerr << ind << "Directive " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << block->keyword() << "] " << block->tabs() << std::endl;
    debug_ast(block->selector(), ind + "~", env);
    debug_ast(block->value(), ind + "+", env);
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Each*>(node)) {
    Each* block = dynamic_cast<Each*>(node);
    std::cerr << ind << "Each " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<For*>(node)) {
    For* block = dynamic_cast<For*>(node);
    std::cerr << ind << "For " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<While*>(node)) {
    While* block = dynamic_cast<While*>(node);
    std::cerr << ind << "While " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << block->tabs() << std::endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Definition*>(node)) {
    Definition* block = dynamic_cast<Definition*>(node);
    std::cerr << ind << "Definition " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [name: " << block->name() << "] ";
    std::cerr << " [type: " << (block->type() == Sass::Definition::Type::MIXIN ? "Mixin " : "Function ") << "] ";
    // this seems to lead to segfaults some times?
    // std::cerr << " [signature: " << block->signature() << "] ";
    std::cerr << " [native: " << block->native_function() << "] ";
    std::cerr << " " << block->tabs() << std::endl;
    debug_ast(block->parameters(), ind + " params: ", env);
    if (block->block()) debug_ast(block->block(), ind + " ", env);
  } else if (dynamic_cast<Mixin_Call*>(node)) {
    Mixin_Call* block = dynamic_cast<Mixin_Call*>(node);
    std::cerr << ind << "Mixin_Call " << block << " " << block->tabs();
    std::cerr << " [" <<  block->name() << "]";
    std::cerr << " [has_content: " << block->has_content() << "] " << std::endl;
    debug_ast(block->arguments(), ind + " args: ");
    if (block->block()) debug_ast(block->block(), ind + " ", env);
  } else if (Ruleset* ruleset = dynamic_cast<Ruleset*>(node)) {
    std::cerr << ind << "Ruleset " << ruleset;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [indent: " << ruleset->tabs() << "]";
    std::cerr << (ruleset->is_invisible() ? " [INVISIBLE]" : "");
    std::cerr << (ruleset->at_root() ? " [@ROOT]" : "");
    std::cerr << (ruleset->is_root() ? " [root]" : "");
    std::cerr << std::endl;
    debug_ast(ruleset->selector(), ind + ">");
    debug_ast(ruleset->block(), ind + " ");
  } else if (dynamic_cast<Block*>(node)) {
    Block* block = dynamic_cast<Block*>(node);
    std::cerr << ind << "Block " << block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << (block->is_invisible() ? " [INVISIBLE]" : "");
    std::cerr << " [indent: " << block->tabs() << "]" << std::endl;
    for(auto i : block->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Textual*>(node)) {
    Textual* expression = dynamic_cast<Textual*>(node);
    std::cerr << ind << "Textual ";
    if (expression->type() == Textual::NUMBER) std::cerr << " [NUMBER]";
    else if (expression->type() == Textual::PERCENTAGE) std::cerr << " [PERCENTAGE]";
    else if (expression->type() == Textual::DIMENSION) std::cerr << " [DIMENSION]";
    else if (expression->type() == Textual::HEX) std::cerr << " [HEX]";
    std::cerr << expression << " [" << expression->value() << "]";
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    if (expression->is_delayed()) std::cerr << " [delayed]";
    std::cerr << std::endl;
  } else if (dynamic_cast<Variable*>(node)) {
    Variable* expression = dynamic_cast<Variable*>(node);
    std::cerr << ind << "Variable " << expression;
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << expression->name() << "]" << std::endl;
    std::string name(expression->name());
    if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env);
  } else if (dynamic_cast<Function_Call_Schema*>(node)) {
    Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node);
    std::cerr << ind << "Function_Call_Schema " << expression;
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << "" << std::endl;
    debug_ast(expression->name(), ind + "name: ", env);
    debug_ast(expression->arguments(), ind + " args: ", env);
  } else if (dynamic_cast<Function_Call*>(node)) {
    Function_Call* expression = dynamic_cast<Function_Call*>(node);
    std::cerr << ind << "Function_Call " << expression;
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << expression->name() << "]";
    if (expression->is_delayed()) std::cerr << " [delayed]";
    if (expression->is_interpolant()) std::cerr << " [interpolant]";
    std::cerr << std::endl;
    debug_ast(expression->arguments(), ind + " args: ", env);
  } else if (dynamic_cast<Arguments*>(node)) {
    Arguments* expression = dynamic_cast<Arguments*>(node);
    std::cerr << ind << "Arguments " << expression;
    if (expression->is_delayed()) std::cerr << " [delayed]";
    std::cerr << " (" << pstate_source_position(node) << ")";
    if (expression->has_named_arguments()) std::cerr << " [has_named_arguments]";
    if (expression->has_rest_argument()) std::cerr << " [has_rest_argument]";
    if (expression->has_keyword_argument()) std::cerr << " [has_keyword_argument]";
    std::cerr << std::endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Argument*>(node)) {
    Argument* expression = dynamic_cast<Argument*>(node);
    std::cerr << ind << "Argument " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << expression->value() << "]";
    std::cerr << " [name: " << expression->name() << "] ";
    std::cerr << " [rest: " << expression->is_rest_argument() << "] ";
    std::cerr << " [keyword: " << expression->is_keyword_argument() << "] " << std::endl;
    debug_ast(expression->value(), ind + " value: ", env);
  } else if (dynamic_cast<Parameters*>(node)) {
    Parameters* expression = dynamic_cast<Parameters*>(node);
    std::cerr << ind << "Parameters " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [has_optional: " << expression->has_optional_parameters() << "] ";
    std::cerr << " [has_rest: " << expression->has_rest_parameter() << "] ";
    std::cerr << std::endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Parameter*>(node)) {
    Parameter* expression = dynamic_cast<Parameter*>(node);
    std::cerr << ind << "Parameter " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [name: " << expression->name() << "] ";
    std::cerr << " [default: " << expression->default_value() << "] ";
    std::cerr << " [rest: " << expression->is_rest_parameter() << "] " << std::endl;
  } else if (dynamic_cast<Unary_Expression*>(node)) {
    Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node);
    std::cerr << ind << "Unary_Expression " << expression;
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " [delayed: " << expression->is_delayed() << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << expression->type() << "]" << std::endl;
    debug_ast(expression->operand(), ind + " operand: ", env);
  } else if (dynamic_cast<Binary_Expression*>(node)) {
    Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node);
    std::cerr << ind << "Binary_Expression " << expression;
    if (expression->is_interpolant()) std::cerr << " [is interpolant] ";
    if (expression->is_left_interpolant()) std::cerr << " [left interpolant] ";
    if (expression->is_right_interpolant()) std::cerr << " [right interpolant] ";
    std::cerr << " [delayed: " << expression->is_delayed() << "] ";
    std::cerr << " [ws_before: " << expression->op().ws_before << "] ";
    std::cerr << " [ws_after: " << expression->op().ws_after << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << expression->type_name() << "]" << std::endl;
    debug_ast(expression->left(), ind + " left:  ", env);
    debug_ast(expression->right(), ind + " right: ", env);
  } else if (dynamic_cast<Map*>(node)) {
    Map* expression = dynamic_cast<Map*>(node);
    std::cerr << ind << "Map " << expression;
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [Hashed]" << std::endl;
    for (auto i : expression->elements()) {
      debug_ast(i.first, ind + " key: ");
      debug_ast(i.second, ind + " val: ");
    }
  } else if (dynamic_cast<List*>(node)) {
    List* expression = dynamic_cast<List*>(node);
    std::cerr << ind << "List " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " (" << expression->length() << ") " <<
      (expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map" : "Space ") <<
      " [delayed: " << expression->is_delayed() << "] " <<
      " [interpolant: " << expression->is_interpolant() << "] " <<
      " [listized: " << expression->from_selector() << "] " <<
      " [arglist: " << expression->is_arglist() << "] " <<
      " [hash: " << expression->hash() << "] " <<
      std::endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Content*>(node)) {
    Content* expression = dynamic_cast<Content*>(node);
    std::cerr << ind << "Content " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [@media:" << expression->media_block() << "]";
    std::cerr << " [Statement]" << std::endl;
  } else if (dynamic_cast<Boolean*>(node)) {
    Boolean* expression = dynamic_cast<Boolean*>(node);
    std::cerr << ind << "Boolean " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " [" << expression->value() << "]" << std::endl;
  } else if (dynamic_cast<Color*>(node)) {
    Color* expression = dynamic_cast<Color*>(node);
    std::cerr << ind << "Color " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [delayed: " << expression->is_delayed() << "] ";
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " [" << expression->r() << ":"  << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << std::endl;
  } else if (dynamic_cast<Number*>(node)) {
    Number* expression = dynamic_cast<Number*>(node);
    std::cerr << ind << "Number " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [interpolant: " << expression->is_interpolant() << "] ";
    std::cerr << " [" << expression->value() << expression->unit() << "]" <<
      " [hash: " << expression->hash() << "] " <<
      std::endl;
  } else if (dynamic_cast<String_Quoted*>(node)) {
    String_Quoted* expression = dynamic_cast<String_Quoted*>(node);
    std::cerr << ind << "String_Quoted " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << prettyprint(expression->value()) << "]";
    if (expression->is_delayed()) std::cerr << " [delayed]";
    if (expression->is_interpolant()) std::cerr << " [interpolant]";
    if (expression->quote_mark()) std::cerr << " [quote_mark: " << expression->quote_mark() << "]";
    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
  } else if (dynamic_cast<String_Constant*>(node)) {
    String_Constant* expression = dynamic_cast<String_Constant*>(node);
    std::cerr << ind << "String_Constant " << expression;
    if (expression->concrete_type()) {
      std::cerr << " " << expression->concrete_type();
    }
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " [" << prettyprint(expression->value()) << "]";
    if (expression->is_delayed()) std::cerr << " [delayed]";
    if (expression->is_interpolant()) std::cerr << " [interpolant]";
    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
  } else if (dynamic_cast<String_Schema*>(node)) {
    String_Schema* expression = dynamic_cast<String_Schema*>(node);
    std::cerr << ind << "String_Schema " << expression;
    std::cerr << " " << expression->concrete_type();
    if (expression->is_delayed()) std::cerr << " [delayed]";
    if (expression->is_interpolant()) std::cerr << " [is interpolant]";
    if (expression->has_interpolant()) std::cerr << " [has interpolant]";
    if (expression->is_left_interpolant()) std::cerr << " [left interpolant] ";
    if (expression->is_right_interpolant()) std::cerr << " [right interpolant] ";
    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<String*>(node)) {
    String* expression = dynamic_cast<String*>(node);
    std::cerr << ind << "String " << expression;
    std::cerr << " " << expression->concrete_type();
    std::cerr << " (" << pstate_source_position(node) << ")";
    if (expression->is_interpolant()) std::cerr << " [interpolant]";
    std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl;
  } else if (dynamic_cast<Expression*>(node)) {
    Expression* expression = dynamic_cast<Expression*>(node);
    std::cerr << ind << "Expression " << expression;
    std::cerr << " (" << pstate_source_position(node) << ")";
    switch (expression->concrete_type()) {
      case Expression::Concrete_Type::NONE: std::cerr << " [NONE]"; break;
      case Expression::Concrete_Type::BOOLEAN: std::cerr << " [BOOLEAN]"; break;
      case Expression::Concrete_Type::NUMBER: std::cerr << " [NUMBER]"; break;
      case Expression::Concrete_Type::COLOR: std::cerr << " [COLOR]"; break;
      case Expression::Concrete_Type::STRING: std::cerr << " [STRING]"; break;
      case Expression::Concrete_Type::LIST: std::cerr << " [LIST]"; break;
      case Expression::Concrete_Type::MAP: std::cerr << " [MAP]"; break;
      case Expression::Concrete_Type::SELECTOR: std::cerr << " [SELECTOR]"; break;
      case Expression::Concrete_Type::NULL_VAL: std::cerr << " [NULL_VAL]"; break;
      case Expression::Concrete_Type::C_WARNING: std::cerr << " [C_WARNING]"; break;
      case Expression::Concrete_Type::C_ERROR: std::cerr << " [C_ERROR]"; break;
      case Expression::Concrete_Type::NUM_TYPES: std::cerr << " [NUM_TYPES]"; break;
    }
    std::cerr << std::endl;
  } else if (dynamic_cast<Has_Block*>(node)) {
    Has_Block* has_block = dynamic_cast<Has_Block*>(node);
    std::cerr << ind << "Has_Block " << has_block;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << has_block->tabs() << std::endl;
    if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Statement*>(node)) {
    Statement* statement = dynamic_cast<Statement*>(node);
    std::cerr << ind << "Statement " << statement;
    std::cerr << " (" << pstate_source_position(node) << ")";
    std::cerr << " " << statement->tabs() << std::endl;
  }

  if (ind == "") std::cerr << "####################################################################\n";
}
Exemple #15
0
void PragmaDeclaration::semantic(Scope *sc)
{   // Should be merged with PragmaStatement

#if IN_LLVM
    Pragma llvm_internal = LLVMnone;
    std::string arg1str;
#endif

    //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
    if (ident == Id::msg)
    {
        if (args)
        {
            for (size_t i = 0; i < args->dim; i++)
            {
                Expression *e = (*args)[i];

                e = e->semantic(sc);
                if (e->op != TOKerror)
                    e = e->optimize(WANTvalue | WANTinterpret);
                if (e->op == TOKerror)
                {   errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
                    return;
                }
                StringExp *se = e->toString();
                if (se)
                {
                    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
                }
                else
                    fprintf(stdmsg, "%s", e->toChars());
            }
            fprintf(stdmsg, "\n");
        }
        goto Lnodecl;
    }
    else if (ident == Id::lib)
    {
        if (!args || args->dim != 1)
            error("string expected for library name");
        else
        {
            Expression *e = (*args)[0];

            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            (*args)[0] = e;
            if (e->op == TOKerror)
                goto Lnodecl;
            StringExp *se = e->toString();
            if (!se)
                error("string expected for library name, not '%s'", e->toChars());
            else if (global.params.verbose)
            {
                char *name = (char *)mem.malloc(se->len + 1);
                memcpy(name, se->string, se->len);
                name[se->len] = 0;
                printf("library   %s\n", name);
                mem.free(name);
            }
        }
        goto Lnodecl;
    }
#if IN_GCC
    else if (ident == Id::GNU_asm)
    {
        if (! args || args->dim != 2)
            error("identifier and string expected for asm name");
        else
        {
            Expression *e;
            Declaration *d = NULL;
            StringExp *s = NULL;

            e = (*args)[0];
            e = e->semantic(sc);
            if (e->op == TOKvar)
            {
                d = ((VarExp *)e)->var;
                if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
                    d = NULL;
            }
            if (!d)
                error("first argument of GNU_asm must be a function or variable declaration");

            e = (*args)[1];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            e = e->toString();
            if (e && ((StringExp *)e)->sz == 1)
                s = ((StringExp *)e);
            else
                error("second argument of GNU_asm must be a character string");

            if (d && s)
                d->c_ident = Lexer::idPool((char*) s->string);
        }
        goto Lnodecl;
    }
#endif
#if DMDV2
    else if (ident == Id::startaddress)
    {
        if (!args || args->dim != 1)
            error("function name expected for start address");
        else
        {
            Expression *e = (*args)[0];
            e = e->semantic(sc);
            e = e->optimize(WANTvalue | WANTinterpret);
            (*args)[0] = e;
            Dsymbol *sa = getDsymbol(e);
            if (!sa || !sa->isFuncDeclaration())
                error("function name expected for start address, not '%s'", e->toChars());
        }
        goto Lnodecl;
    }
#endif
#if TARGET_NET
    else if (ident == Lexer::idPool("assembly"))
    {
    }
#endif // TARGET_NET
#if IN_LLVM
    else if ((llvm_internal = DtoGetPragma(sc, this, arg1str)) != LLVMnone)
    {
        // nothing to do anymore
    }
#endif
    else if (global.params.ignoreUnsupportedPragmas)
    {
        if (global.params.verbose)
        {
            /* Print unrecognized pragmas
             */
            printf("pragma    %s", ident->toChars());
            if (args)
            {
                for (size_t i = 0; i < args->dim; i++)
                {
                    Expression *e = (*args)[i];
                    // ignore errors in ignored pragmas.
                    global.gag++;
                    unsigned errors_save = global.errors;

                    e = e->semantic(sc);
                    e = e->optimize(WANTvalue | WANTinterpret);
                    if (i == 0)
                        printf(" (");
                    else
                        printf(",");
                    printf("%s", e->toChars());

                    // restore error state.
                    global.gag--;
                    global.errors = errors_save;
                }
                if (args->dim)
                    printf(")");
            }
            printf("\n");
        }
    }
    else
        error("unrecognized pragma(%s)", ident->toChars());

Ldecl:
    if (decl)
    {
        for (size_t i = 0; i < decl->dim; i++)
        {
            Dsymbol *s = (*decl)[i];

            s->semantic(sc);

#if IN_LLVM
            DtoCheckPragma(this, s, llvm_internal, arg1str);
#endif
        }
    }
    return;

Lnodecl:
    if (decl)
    {
        error("pragma is missing closing ';'");
        goto Ldecl; // do them anyway, to avoid segfaults.
    }
}
Exemple #16
0
/**
 * Loads LX task structure from XCSoar task structure
 * @param decl  The declaration
 */
static bool
LoadTask(LX::Declaration &lxDevice_Declaration, const Declaration &declaration)
{
  if (declaration.Size() > 10)
    return false;

  if (declaration.Size() < 2)
      return false;

  memset((void*)lxDevice_Declaration.unknown1, 0,
          sizeof(lxDevice_Declaration.unknown1));

  BrokenDate DeclDate;
  DeclDate.day = 1;
  DeclDate.month = 1;
  DeclDate.year = 2010;

  if (DeclDate.day > 0 && DeclDate.day < 32
      && DeclDate.month > 0 && DeclDate.month < 13) {
    lxDevice_Declaration.dayinput = (unsigned char)DeclDate.day;
    lxDevice_Declaration.monthinput = (unsigned char)DeclDate.month;
    int iCentury = DeclDate.year / 100; // Todo: if no gps fix, use system time
    iCentury *= 100;
    lxDevice_Declaration.yearinput = (unsigned char)(DeclDate.year - iCentury);
  }
  else {
    lxDevice_Declaration.dayinput = (unsigned char)1;
    lxDevice_Declaration.monthinput = (unsigned char)1;
    lxDevice_Declaration.yearinput = (unsigned char)10;
  }
  lxDevice_Declaration.dayuser = lxDevice_Declaration.dayinput;
  lxDevice_Declaration.monthuser = lxDevice_Declaration.monthinput;
  lxDevice_Declaration.yearuser = lxDevice_Declaration.yearinput;
  lxDevice_Declaration.taskid = 0;
  lxDevice_Declaration.numtps = declaration.Size();

  for (unsigned i = 0; i < LX::NUMTPS; i++) {
    if (i == 0) { // takeoff
      lxDevice_Declaration.tptypes[i] = 3;
      lxDevice_Declaration.Latitudes[i] = 0;
      lxDevice_Declaration.Longitudes[i] = 0;
      copy_space_padded(lxDevice_Declaration.WaypointNames[i], _T("TAKEOFF"),
        sizeof(lxDevice_Declaration.WaypointNames[i]));


    } else if (i <= declaration.Size()) {
      lxDevice_Declaration.tptypes[i] = 1;
      lxDevice_Declaration.Longitudes[i] =
        AngleToLX(declaration.GetLocation(i - 1).longitude);
      lxDevice_Declaration.Latitudes[i] =
        AngleToLX(declaration.GetLocation(i - 1).latitude);
      copy_space_padded(lxDevice_Declaration.WaypointNames[i],
                        declaration.GetName(i - 1),
                        sizeof(lxDevice_Declaration.WaypointNames[i]));

    } else if (i == declaration.Size() + 1) { // landing
      lxDevice_Declaration.tptypes[i] = 2;
      lxDevice_Declaration.Longitudes[i] = 0;
      lxDevice_Declaration.Latitudes[i] = 0;
      copy_space_padded(lxDevice_Declaration.WaypointNames[i], _T("LANDING"),
          sizeof(lxDevice_Declaration.WaypointNames[i]));

    } else { // unused
      lxDevice_Declaration.tptypes[i] = 0;
      lxDevice_Declaration.Longitudes[i] = 0;
      lxDevice_Declaration.Latitudes[i] = 0;
      memset((void*)lxDevice_Declaration.WaypointNames[i], 0, 9);
    }
  }

  return true;
}
Exemple #17
0
Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
{
    //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
    //if (strcmp(ident->toChars(),"c") == 0) *(char*)0=0;

    // Look in symbols declared in this module
    Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
    //printf("\ts = %p, imports = %p, %d\n", s, imports, imports ? imports->dim : 0);
    if (s)
    {
        //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
    }
    else if (imports)
    {
        OverloadSet *a = NULL;

        // Look in imported modules
        for (size_t i = 0; i < imports->dim; i++)
        {   Dsymbol *ss = (*imports)[i];
            Dsymbol *s2;

            // If private import, don't search it
            if (flags & 1 && prots[i] == PROTprivate)
                continue;

            //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
            /* Don't find private members if ss is a module
             */
            s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
            if (!s)
                s = s2;
            else if (s2 && s != s2)
            {
                if (s->toAlias() == s2->toAlias())
                {
                    /* After following aliases, we found the same
                     * symbol, so it's not an ambiguity.  But if one
                     * alias is deprecated or less accessible, prefer
                     * the other.
                     */
                    if (s->isDeprecated() ||
                        s2->prot() > s->prot() && s2->prot() != PROTnone)
                        s = s2;
                }
                else
                {
                    /* Two imports of the same module should be regarded as
                     * the same.
                     */
                    Import *i1 = s->isImport();
                    Import *i2 = s2->isImport();
                    if (!(i1 && i2 &&
                          (i1->mod == i2->mod ||
                           (!i1->parent->isImport() && !i2->parent->isImport() &&
                            i1->ident->equals(i2->ident))
                          )
                         )
                       )
                    {
                        /* If both s2 and s are overloadable (though we only
                         * need to check s once)
                         */
                        if (s2->isOverloadable() && (a || s->isOverloadable()))
                        {   if (!a)
                                a = new OverloadSet();
                            /* Don't add to a[] if s2 is alias of previous sym
                             */
                            for (size_t j = 0; j < a->a.dim; j++)
                            {   Dsymbol *s3 = a->a[j];
                                if (s2->toAlias() == s3->toAlias())
                                {
                                    if (s3->isDeprecated() ||
                                        s2->prot() > s3->prot() && s2->prot() != PROTnone)
                                        a->a[j] = s2;
                                    goto Lcontinue;
                                }
                            }
                            a->push(s2);
                        Lcontinue:
                            continue;
                        }
                        if (flags & 4)          // if return NULL on ambiguity
                            return NULL;
                        if (!(flags & 2))
                            ScopeDsymbol::multiplyDefined(loc, s, s2);
                        break;
                    }
                }
            }
        }

        /* Build special symbol if we had multiple finds
         */
        if (a)
        {   assert(s);
            a->push(s);
            s = a;
        }

        if (s)
        {
            Declaration *d = s->isDeclaration();
            if (d && d->protection == PROTprivate &&
                !d->parent->isTemplateMixin() &&
                !(flags & 2))
                error(loc, "%s is private", d->toPrettyChars());
        }
    }
    return s;
}
Exemple #18
0
inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
{
  if (node == 0) return;
  if (ind == "") cerr << "####################################################################\n";
  if (dynamic_cast<Bubble*>(node)) {
    Bubble* bubble = dynamic_cast<Bubble*>(node);
    cerr << ind << "Bubble " << bubble;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << bubble->tabs();
    cerr << endl;
  } else if (dynamic_cast<At_Root_Block*>(node)) {
    At_Root_Block* root_block = dynamic_cast<At_Root_Block*>(node);
    cerr << ind << "At_Root_Block " << root_block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << root_block->tabs();
    cerr << endl;
    if (root_block->block()) for(auto i : root_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Selector_List*>(node)) {
    Selector_List* selector = dynamic_cast<Selector_List*>(node);
    cerr << ind << "Selector_List " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [block:" << selector->last_block() << "]";
    cerr << (selector->last_block() && selector->last_block()->is_root() ? " [root]" : "");
    cerr << " [@media:" << selector->media_block() << "]";
    cerr << (selector->is_optional() ? " [is_optional]": " -");
    cerr << (selector->has_line_break() ? " [line-break]": " -");
    cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    cerr << endl;

    for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }

//  } else if (dynamic_cast<Expression*>(node)) {
//    Expression* expression = dynamic_cast<Expression*>(node);
//    cerr << ind << "Expression " << expression << " " << expression->concrete_type() << endl;

  } else if (dynamic_cast<Parent_Selector*>(node)) {
    Parent_Selector* selector = dynamic_cast<Parent_Selector*>(node);
    cerr << ind << "Parent_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << endl;
    debug_ast(selector->selector(), ind + "->", env);

  } else if (dynamic_cast<Complex_Selector*>(node)) {
    Complex_Selector* selector = dynamic_cast<Complex_Selector*>(node);
    cerr << ind << "Complex_Selector " << selector
      << " (" << pstate_source_position(node) << ")"
      << " [block:" << selector->last_block() << "]"
      << " [weight:" << longToHex(selector->specificity()) << "]"
      << (selector->last_block() && selector->last_block()->is_root() ? " [root]" : "")
      << " [@media:" << selector->media_block() << "]"
      << (selector->is_optional() ? " [is_optional]": " -")
      << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -") << " -> ";
      switch (selector->combinator()) {
        case Complex_Selector::PARENT_OF:   cerr << "{>}"; break;
        case Complex_Selector::PRECEDES:    cerr << "{~}"; break;
        case Complex_Selector::ADJACENT_TO: cerr << "{+}"; break;
        case Complex_Selector::ANCESTOR_OF: cerr << "{ }"; break;
      }
    cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << endl;
    debug_ast(selector->head(), ind + " ", env);
    debug_ast(selector->tail(), ind + "-", env);
  } else if (dynamic_cast<Compound_Selector*>(node)) {
    Compound_Selector* selector = dynamic_cast<Compound_Selector*>(node);
    cerr << ind << "Compound_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [block:" << selector->last_block() << "]";
    cerr << " [weight:" << longToHex(selector->specificity()) << "]";
    // cerr << (selector->last_block() && selector->last_block()->is_root() ? " [root]" : "");
    cerr << " [@media:" << selector->media_block() << "]";
    cerr << (selector->is_optional() ? " [is_optional]": " -");
    cerr << (selector->has_line_break() ? " [line-break]": " -");
    cerr << (selector->has_line_feed() ? " [line-feed]": " -");
    cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << endl;
    for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Propset*>(node)) {
    Propset* selector = dynamic_cast<Propset*>(node);
    cerr << ind << "Propset " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << selector->tabs() << endl;
    if (selector->block()) for(auto i : selector->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Wrapped_Selector*>(node)) {
    Wrapped_Selector* selector = dynamic_cast<Wrapped_Selector*>(node);
    cerr << ind << "Wrapped_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << selector->name() << ">>" << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
    debug_ast(selector->selector(), ind + " () ", env);
  } else if (dynamic_cast<Pseudo_Selector*>(node)) {
    Pseudo_Selector* selector = dynamic_cast<Pseudo_Selector*>(node);
    cerr << ind << "Pseudo_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << selector->name() << ">>" << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
    debug_ast(selector->expression(), ind + " <= ", env);
  } else if (dynamic_cast<Attribute_Selector*>(node)) {
    Attribute_Selector* selector = dynamic_cast<Attribute_Selector*>(node);
    cerr << ind << "Attribute_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << selector->name() << ">>" << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
    debug_ast(selector->value(), ind + "[" + selector->matcher() + "] ", env);
  } else if (dynamic_cast<Selector_Qualifier*>(node)) {
    Selector_Qualifier* selector = dynamic_cast<Selector_Qualifier*>(node);
    cerr << ind << "Selector_Qualifier " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << selector->name() << ">>" << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
  } else if (dynamic_cast<Type_Selector*>(node)) {
    Type_Selector* selector = dynamic_cast<Type_Selector*>(node);
    cerr << ind << "Type_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << selector->name() << ">>" << (selector->has_line_break() ? " [line-break]": " -") <<
      " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << endl;
  } else if (dynamic_cast<Selector_Placeholder*>(node)) {

    Selector_Placeholder* selector = dynamic_cast<Selector_Placeholder*>(node);
    cerr << ind << "Selector_Placeholder [" << selector->name() << "] " << selector
      << " [block:" << selector->last_block() << "]"
      << " [@media:" << selector->media_block() << "]"
      << (selector->is_optional() ? " [is_optional]": " -")
      << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << endl;

  } else if (dynamic_cast<Selector_Reference*>(node)) {
    Selector_Reference* selector = dynamic_cast<Selector_Reference*>(node);
    cerr << ind << "Selector_Reference " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " @ref " << selector->selector() << endl;
  } else if (dynamic_cast<Simple_Selector*>(node)) {
    Simple_Selector* selector = dynamic_cast<Simple_Selector*>(node);
    cerr << ind << "Simple_Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;

  } else if (dynamic_cast<Selector_Schema*>(node)) {
    Selector_Schema* selector = dynamic_cast<Selector_Schema*>(node);
    cerr << ind << "Selector_Schema " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [block:" << selector->last_block() << "]"
      << (selector->last_block() && selector->last_block()->is_root() ? " [root]" : "")
      << " [@media:" << selector->media_block() << "]"
      << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << endl;

    debug_ast(selector->contents(), ind + " ");
    // for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); }

  } else if (dynamic_cast<Selector*>(node)) {
    Selector* selector = dynamic_cast<Selector*>(node);
    cerr << ind << "Selector " << selector;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << (selector->has_line_break() ? " [line-break]": " -")
      << (selector->has_line_feed() ? " [line-feed]": " -")
    << endl;

  } else if (dynamic_cast<Media_Query_Expression*>(node)) {
    Media_Query_Expression* block = dynamic_cast<Media_Query_Expression*>(node);
    cerr << ind << "Media_Query_Expression " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << (block->is_interpolated() ? " [is_interpolated]": " -")
    << endl;
    debug_ast(block->feature(), ind + " f) ");
    debug_ast(block->value(), ind + " v) ");

  } else if (dynamic_cast<Media_Query*>(node)) {
    Media_Query* block = dynamic_cast<Media_Query*>(node);
    cerr << ind << "Media_Query " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << (block->is_negated() ? " [is_negated]": " -")
      << (block->is_restricted() ? " [is_restricted]": " -")
    << endl;
    debug_ast(block->media_type(), ind + " ");
    for(auto i : block->elements()) { debug_ast(i, ind + " ", env); }

  } else if (dynamic_cast<Media_Block*>(node)) {
    Media_Block* block = dynamic_cast<Media_Block*>(node);
    cerr << ind << "Media_Block " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    debug_ast(block->media_queries(), ind + " =@ ");
    debug_ast(block->selector(), ind + " -@ ");
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Feature_Block*>(node)) {
    Feature_Block* block = dynamic_cast<Feature_Block*>(node);
    cerr << ind << "Feature_Block " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Block*>(node)) {
    Block* root_block = dynamic_cast<Block*>(node);
    cerr << ind << "Block " << root_block;
    cerr << " (" << pstate_source_position(node) << ")";
    if (root_block->is_root()) cerr << " [root]";
    cerr << " " << root_block->tabs() << endl;
    if (root_block->block()) for(auto i : root_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Warning*>(node)) {
    Warning* block = dynamic_cast<Warning*>(node);
    cerr << ind << "Warning " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Error*>(node)) {
    Error* block = dynamic_cast<Error*>(node);
    cerr << ind << "Error " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Debug*>(node)) {
    Debug* block = dynamic_cast<Debug*>(node);
    cerr << ind << "Debug " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Comment*>(node)) {
    Comment* block = dynamic_cast<Comment*>(node);
    cerr << ind << "Comment " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() <<
      " <" << prettyprint(block->pstate().token.ws_before()) << ">" << endl;
    debug_ast(block->text(), ind + "// ", env);
  } else if (dynamic_cast<If*>(node)) {
    If* block = dynamic_cast<If*>(node);
    cerr << ind << "If " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Return*>(node)) {
    Return* block = dynamic_cast<Return*>(node);
    cerr << ind << "Return " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Extension*>(node)) {
    Extension* block = dynamic_cast<Extension*>(node);
    cerr << ind << "Extension " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    debug_ast(block->selector(), ind + "-> ", env);
  } else if (dynamic_cast<Content*>(node)) {
    Content* block = dynamic_cast<Content*>(node);
    cerr << ind << "Content " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Import_Stub*>(node)) {
    Import_Stub* block = dynamic_cast<Import_Stub*>(node);
    cerr << ind << "Import_Stub " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
  } else if (dynamic_cast<Import*>(node)) {
    Import* block = dynamic_cast<Import*>(node);
    cerr << ind << "Import " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    // vector<string>         files_;
    for (auto imp : block->urls()) debug_ast(imp, "@ ", env);
  } else if (dynamic_cast<Assignment*>(node)) {
    Assignment* block = dynamic_cast<Assignment*>(node);
    cerr << ind << "Assignment " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " <<" << block->variable() << ">> " << block->tabs() << endl;
    debug_ast(block->value(), ind + "=", env);
  } else if (dynamic_cast<Declaration*>(node)) {
    Declaration* block = dynamic_cast<Declaration*>(node);
    cerr << ind << "Declaration " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    debug_ast(block->property(), ind + " prop: ", env);
    debug_ast(block->value(), ind + " value: ", env);
  } else if (dynamic_cast<Keyframe_Rule*>(node)) {
    Keyframe_Rule* has_block = dynamic_cast<Keyframe_Rule*>(node);
    cerr << ind << "Keyframe_Rule " << has_block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << has_block->tabs() << endl;
    if (has_block->selector()) debug_ast(has_block->selector(), ind + "@");
    if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<At_Rule*>(node)) {
    At_Rule* block = dynamic_cast<At_Rule*>(node);
    cerr << ind << "At_Rule " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << block->keyword() << "] " << block->tabs() << endl;
    debug_ast(block->value(), ind + "+", env);
    debug_ast(block->selector(), ind + "~", env);
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Each*>(node)) {
    Each* block = dynamic_cast<Each*>(node);
    cerr << ind << "Each " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<For*>(node)) {
    For* block = dynamic_cast<For*>(node);
    cerr << ind << "For " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<While*>(node)) {
    While* block = dynamic_cast<While*>(node);
    cerr << ind << "While " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Definition*>(node)) {
    Definition* block = dynamic_cast<Definition*>(node);
    cerr << ind << "Definition " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Mixin_Call*>(node)) {
    Mixin_Call* block = dynamic_cast<Mixin_Call*>(node);
    cerr << ind << "Mixin_Call " << block << " " << block->tabs() << endl;
    if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Ruleset*>(node)) {
    Ruleset* ruleset = dynamic_cast<Ruleset*>(node);
    cerr << ind << "Ruleset " << ruleset;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << ruleset->tabs() << endl;
    debug_ast(ruleset->selector(), ind + " ");
    if (ruleset->block()) for(auto i : ruleset->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Block*>(node)) {
    Block* block = dynamic_cast<Block*>(node);
    cerr << ind << "Block " << block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << block->tabs() << endl;
    for(auto i : block->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Textual*>(node)) {
    Textual* expression = dynamic_cast<Textual*>(node);
    cerr << ind << "Textual ";
    if (expression->type() == Textual::NUMBER) cerr << " [NUMBER]";
    else if (expression->type() == Textual::PERCENTAGE) cerr << " [PERCENTAGE]";
    else if (expression->type() == Textual::DIMENSION) cerr << " [DIMENSION]";
    else if (expression->type() == Textual::HEX) cerr << " [HEX]";
    cerr << expression << " [" << expression->value() << "]" << endl;
  } else if (dynamic_cast<Variable*>(node)) {
    Variable* expression = dynamic_cast<Variable*>(node);
    cerr << ind << "Variable " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->name() << "]" << endl;
    string name(expression->name());
    if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env);
  } else if (dynamic_cast<Function_Call_Schema*>(node)) {
    Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node);
    cerr << ind << "Function_Call_Schema " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << "" << endl;
    debug_ast(expression->name(), ind + "name: ", env);
    debug_ast(expression->arguments(), ind + " args: ", env);
  } else if (dynamic_cast<Function_Call*>(node)) {
    Function_Call* expression = dynamic_cast<Function_Call*>(node);
    cerr << ind << "Function_Call " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->name() << "]" << endl;
    debug_ast(expression->arguments(), ind + " args: ", env);
  } else if (dynamic_cast<Arguments*>(node)) {
    Arguments* expression = dynamic_cast<Arguments*>(node);
    cerr << ind << "Arguments " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Argument*>(node)) {
    Argument* expression = dynamic_cast<Argument*>(node);
    cerr << ind << "Argument " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->value() << "]" << endl;
    debug_ast(expression->value(), ind + " value: ", env);
  } else if (dynamic_cast<Unary_Expression*>(node)) {
    Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node);
    cerr << ind << "Unary_Expression " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->type() << "]" << endl;
    debug_ast(expression->operand(), ind + " operand: ", env);
  } else if (dynamic_cast<Binary_Expression*>(node)) {
    Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node);
    cerr << ind << "Binary_Expression " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->type() << "]" << endl;
    debug_ast(expression->left(), ind + " left:  ", env);
    debug_ast(expression->right(), ind + " right: ", env);
  } else if (dynamic_cast<Map*>(node)) {
    Map* expression = dynamic_cast<Map*>(node);
    cerr << ind << "Map " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [Hashed]" << endl;
  } else if (dynamic_cast<List*>(node)) {
    List* expression = dynamic_cast<List*>(node);
    cerr << ind << "List " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " (" << expression->length() << ") " <<
      (expression->separator() == Sass::List::Separator::COMMA ? "Comma " : "Space ") <<
      " [delayed: " << expression->is_delayed() << "] " <<
      " [interpolant: " << expression->is_interpolant() << "] " <<
      endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Content*>(node)) {
    Content* expression = dynamic_cast<Content*>(node);
    cerr << ind << "Content " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [Statement]" << endl;
  } else if (dynamic_cast<Boolean*>(node)) {
    Boolean* expression = dynamic_cast<Boolean*>(node);
    cerr << ind << "Boolean " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->value() << "]" << endl;
  } else if (dynamic_cast<Color*>(node)) {
    Color* expression = dynamic_cast<Color*>(node);
    cerr << ind << "Color " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->r() << ":"  << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << endl;
  } else if (dynamic_cast<Number*>(node)) {
    Number* expression = dynamic_cast<Number*>(node);
    cerr << ind << "Number " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << expression->value() << expression->unit() << "]" << endl;
  } else if (dynamic_cast<String_Quoted*>(node)) {
    String_Quoted* expression = dynamic_cast<String_Quoted*>(node);
    cerr << ind << "String_Quoted : " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << prettyprint(expression->value()) << "]" <<
      (expression->is_delayed() ? " {delayed}" : "") <<
      (expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
      (expression->quote_mark() != 0 ? " {qm:" + string(1, expression->quote_mark()) + "}" : "") <<
      " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
  } else if (dynamic_cast<String_Constant*>(node)) {
    String_Constant* expression = dynamic_cast<String_Constant*>(node);
    cerr << ind << "String_Constant : " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " [" << prettyprint(expression->value()) << "]" <<
      (expression->is_delayed() ? " {delayed}" : "") <<
      (expression->sass_fix_1291() ? " {sass_fix_1291}" : "") <<
      " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << endl;
  } else if (dynamic_cast<String_Schema*>(node)) {
    String_Schema* expression = dynamic_cast<String_Schema*>(node);
    cerr << ind << "String_Schema " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << expression->concrete_type() <<
      (expression->has_interpolants() ? " {has_interpolants}" : "") <<
      endl;
    for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<String*>(node)) {
    String* expression = dynamic_cast<String*>(node);
    cerr << ind << "String " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << expression->concrete_type() <<
      " " << (expression->sass_fix_1291() ? "{sass_fix_1291}" : "") <<
      endl;
  } else if (dynamic_cast<Expression*>(node)) {
    Expression* expression = dynamic_cast<Expression*>(node);
    cerr << ind << "Expression " << expression;
    cerr << " (" << pstate_source_position(node) << ")";
    switch (expression->concrete_type()) {
      case Expression::Concrete_Type::NONE: cerr << " [NONE]"; break;
      case Expression::Concrete_Type::BOOLEAN: cerr << " [BOOLEAN]"; break;
      case Expression::Concrete_Type::NUMBER: cerr << " [NUMBER]"; break;
      case Expression::Concrete_Type::COLOR: cerr << " [COLOR]"; break;
      case Expression::Concrete_Type::STRING: cerr << " [STRING]"; break;
      case Expression::Concrete_Type::LIST: cerr << " [LIST]"; break;
      case Expression::Concrete_Type::MAP: cerr << " [MAP]"; break;
      case Expression::Concrete_Type::SELECTOR: cerr << " [SELECTOR]"; break;
      case Expression::Concrete_Type::NULL_VAL: cerr << " [NULL_VAL]"; break;
      case Expression::Concrete_Type::NUM_TYPES: cerr << " [NUM_TYPES]"; break;
    }
    cerr << endl;
  } else if (dynamic_cast<Has_Block*>(node)) {
    Has_Block* has_block = dynamic_cast<Has_Block*>(node);
    cerr << ind << "Has_Block " << has_block;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << has_block->tabs() << endl;
    if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); }
  } else if (dynamic_cast<Statement*>(node)) {
    Statement* statement = dynamic_cast<Statement*>(node);
    cerr << ind << "Statement " << statement;
    cerr << " (" << pstate_source_position(node) << ")";
    cerr << " " << statement->tabs() << endl;
  }

  if (ind == "") cerr << "####################################################################\n";
}