Ejemplo n.º 1
0
/* main program logic:  spawn crud to see what happens */
int                 main
    (
    int             argc,
    char * *        argv,
    char * *        env
    )
    {
    char            mode;
    int             cnt;

    mode = toupper( argv[ 1 ][ 0 ]);
    cnt = atoi( argv[ 2 ]);
    if ( mode == 'T')
        {
        do_threads( cnt);
        }  // threads?
    else if ( mode == 'F')
        {
        do_forks( cnt);
        }  // forks?
    else if ( mode == 'S')
        {
        do_sequence( cnt);
        }  // sequential processing?
    else
        {
        die( "Arg 1 must be T (thread), F (fork), or S (sequential)");
        }
    return 0;
    }
Ejemplo n.º 2
0
// Type Function
// -----------------------------------------------------------------------------
// function-type-parameter = [ "identifier" ":" ] type ;
// function-type = "(" ")" "->" type
//               | "(" function-type-parameter { "," function-type-parameter } [ "," ] ")" "->" type
//               ;
// -----------------------------------------------------------------------------
bool Parser::parse_type_function(Ref<ast::TypeTuple> initial, bool in_params) {
  // Declare the tuple-type node
  Ref<ast::TypeFunction> node = new ast::TypeFunction(initial->span);

  // Consume parsed type parameters (so far)
  for (auto& elem : initial->elements) {
    node->parameters.push_back(new ast::TypeParameter(
      elem->span,
      "",
      elem,
      false
    ));
  }

  if (in_params) {
    // Iterate and parse each parameter in the sequence
    if (!do_sequence(Token::Type::RightParenthesis, [&, this]() {
      // Check for `[MUTABLE] IDENTIFIER ":"` to allow for the keyword
      auto begin = _t.peek(0)->span;
      std::string keyword = "";
      bool is_mutable = false;
      if ((_t.peek(0)->type == Token::Type::Identifier &&
           _t.peek(1)->type == Token::Type::Colon) || (
           _t.peek(0)->type == Token::Type::Mutable &&
           _t.peek(1)->type == Token::Type::Identifier &&
           _t.peek(2)->type == Token::Type::Colon)) {

        if (_t.peek(0)->type == Token::Type::Mutable) {
          _t.pop();
          is_mutable = true;
        }

        auto id = expect<ast::Identifier>(&Parser::parse_identifier);
        keyword = id->text;
        _t.pop(); // ":"
      }

      // Parse the element
      auto type = expect(&Parser::parse_type);
      if (!type) return false;

      // Push the element
      node->parameters.push_back(new ast::TypeParameter(
        begin.extend(type->span),
        keyword,
        type,
        is_mutable
      ));

      return true;
    })) return false;

    // Expect a `)`
    auto tok = expect(Token::Type::RightParenthesis);
    if (!tok) return false;
    node->span = node->span.extend(tok->span);
  }

  // Expect a `->`
  auto tok = expect(Token::Type::Arrow);
  if (!tok) return false;
  node->span = node->span.extend(tok->span);

  node->result = expect<ast::Type>(&Parser::parse_type);
  if (!node->result) return false;

  // Push the node
  _stack.push_front(node);

  return true;
}
Ejemplo n.º 3
0
// Pattern
// -----------------------------------------------------------------------------
// pattern-wildcard = "_" ;
// pattern-literal = literal ;
// pattern-identifier = [ "mutable" ] IDENTIFIER ;
// pattern-tuple =
//    | "(" ")"
//    | "(" pattern "," ")"
//    | "(" pattern "," pattern "," pattern [ "," ] ")"
//    ;
// pattern = pattern-wildcard
//         | pattern-literal
//         | pattern-identifier
//         | pattern-tuple ;
// -----------------------------------------------------------------------------
bool Parser::parse_pattern() {
  auto tok = _t.peek(0);

  // Check for a "_" which would indicate a wildcard pattern
  if (tok->type == Token::Type::Underscore) {
    auto tok = _t.pop();

    _stack.push_front(new ast::PatternWildcard(tok->span));
    return true;
  }

  // Check for a `mut` which could optionally preceed an identifier pattern
  bool mut = false;
  if (tok->type == Token::Type::Mutable
      && _t.peek(1)->type == Token::Type::Identifier) {
    _t.pop();
    tok = _t.peek(0);
    mut = true;
  }

  // Check for an IDENTIFIER which would indicate a simple identifier pattern
  if (tok->type == Token::Type::Identifier) {
    auto ident = expect<ast::Identifier>(&Parser::parse_identifier);
    if (!ident) return false;

    _stack.push_front(new ast::PatternIdentifier(tok->span, ident->text, mut));
    return true;
  }

  // Check for a `(` which would be the start of a tuple pattern
  if (tok->type == Token::Type::LeftParenthesis) {
    _t.pop();

    // Declare the tuple-pattern node
    Ref<ast::PatternTuple> node = new ast::PatternTuple(tok->span);

    // Check for an immediate `)` which makes this an empty tuple
    if (_t.peek(0)->type == Token::Type::RightParenthesis) {
      tok = _t.pop();
      node->span = node->span.extend(tok->span);
      _stack.push_front(node);
      return true;
    }

    // Parse the first element (which is a special case for tuples)
    auto elem0 = expect(&Parser::parse_pattern);
    if (!elem0) return false;
    node->elements.push_back(elem0);

    // Expect a comma to follow the first element (to prove we're a tuple)
    if (!expect(Token::Type::Comma)) return false;

    // Iterate and parse each remaining element in the sequence
    if (!do_sequence(Token::Type::RightParenthesis, [&, this]() {
      // Parse the element
      auto elem = expect(&Parser::parse_pattern);
      if (!elem) return false;

      // Push the element
      node->elements.push_back(elem);

      return true;
    })) return false;

    // Expect `)`
    if (!(tok = expect(Token::Type::RightParenthesis))) { return false; }

    // Push the node
    node->span = node->span.extend(tok->span);
    _stack.push_front(node);

    return true;
  }

  // Check for and parse a literal for a literal pattern
  if (tok->type == Token::Type::Float ||
      tok->type == Token::Type::String ||
      tok->type == Token::Type::Integer ||
      tok->type == Token::Type::True ||
      tok->type == Token::Type::None ||
      tok->type == Token::Type::False) {
    auto literal = expect<ast::Literal>(&Parser::parse_literal);
    if (!literal) return false;

    _stack.push_front(new ast::PatternLiteral(tok->span, literal));
    return true;
  }

  // TODO: Additional patterns

  // Fail; could not match a pattern
  // TODO: Should probably have shorter error message
  expect({
    Token::Type::Mutable,
    Token::Type::Identifier,
    Token::Type::LeftParenthesis,
    Token::Type::Underscore,
    Token::Type::Float,
    Token::Type::True,
    Token::Type::False,
    Token::Type::Integer,
    Token::Type::String,
    Token::Type::None
  });

  return false;
}
Ejemplo n.º 4
0
// Type
// -----------------------------------------------------------------------------
// type = identifier
//      | "None"
//      | "*" type
//      | "(" ")"
//      | "(" type "," ")"
//      | "(" type "," type { "," type } [ "," ] ")"
//      | function-type
//      ;
// -----------------------------------------------------------------------------
bool Parser::parse_type() {
  auto tok = _t.peek(0);

  if (!([&, this]() -> bool {
    // Check for `None` to indicate the unit type
    if (tok->type == Token::Type::None) {
      auto tok = _t.pop();

      _stack.push_front(new ast::TypeNone(tok->span));
      return true;
    }

    // Check for an identifier (for a simple type)
    if (tok->type == Token::Type::Identifier) {
      std::vector<std::string> segments;
      auto span = tok->span;

      for (unsigned i = 0; ; i++) {
        // Expect a `.` (unless this is the first identifier)
        if (i > 0 && !expect(Token::Type::Period)) return false;

        // Parse the identifier
        auto id_node = expect<ast::Identifier>(&Parser::parse_identifier);
        if (!id_node) return false;

        segments.push_back(id_node->text);

        // Extend the span
        span = span.extend(id_node->span);

        // Check for a `.` that could continue this into a path
        if (_t.peek(0)->type != Token::Type::Period) break;
      }

      _stack.push_front(new ast::TypePath(
        span,
        segments
      ));

      return true;
    }

    // Check for a `type(..)` to indicate a typeOf
    if (tok->type == Token::Type::TypeOf) {
      auto span = tok->span;
      _t.pop();

      // Expect a `(`
      if (!expect(Token::Type::LeftParenthesis)) return false;

      // Parse an expression
      if (!parse_expression()) return false;
      auto expr = _stack.front();
      _stack.pop_front();

      // Expect a `)`
      auto last_tok = expect(Token::Type::RightParenthesis);
      if (!last_tok) return false;

      _stack.push_front(new ast::TypeOf(
        span.extend(last_tok->span),
        expr
      ));

      return true;
    }

    // Check for a `*` to indicate a pointer type
    if (tok->type == Token::Type::Asterisk) {
      _t.pop();

      // Check for `mutable` to indicate a mutable pointee
      bool is_mutable = false;
      if (_t.peek(0)->type == Token::Type::Mutable) {
        _t.pop();
        is_mutable = true;
      }

      // Parse the pointee type
      auto pointee = expect(&Parser::parse_type);
      if (!pointee) return false;

      _stack.push_front(new ast::TypePointer(
        tok->span.extend(pointee->span),
        pointee,
        is_mutable
      ));

      return true;
    }

    // Check for a `(` which would be the start of a tuple type OR a
    // function type
    if (tok->type == Token::Type::LeftParenthesis) {
      _t.pop();

      // Declare the tuple-type node
      Ref<ast::TypeTuple> node = new ast::TypeTuple(tok->span);

      // Check for an immediate `)` which makes this an empty tuple
      if (_t.peek(0)->type == Token::Type::RightParenthesis) {
        tok = _t.pop();
        node->span = node->span.extend(tok->span);

        // Check for a "->" (which would make this definitely be
        // a function type)
        if (_t.peek(0)->type == Token::Type::Arrow) {
          return parse_type_function(node, false);
        }

        _stack.push_front(node);
        return true;
      }

      // Check for a named parameter (which would make this definitely be
      // a function type)
      if (_t.peek(0)->type == Token::Type::Identifier &&
          _t.peek(1)->type == Token::Type::Colon) {
        return parse_type_function(node);
      }

      // Parse the first element (which is a special case for tuples)
      auto elem0 = expect(&Parser::parse_type);
      if (!elem0) return false;
      node->elements.push_back(elem0);

      // Check for an arrow (which would make this definitely be
      // a function type)
      if (_t.peek(0)->type == Token::Type::RightParenthesis &&
          _t.peek(1)->type == Token::Type::Arrow) {
        _t.pop();
        return parse_type_function(node, false);
      }

      // Check for an immediate `)` which makes this just a grouping
      if (_t.peek()->type == Token::Type::RightParenthesis) {
        _t.pop();
        _stack.push_front(elem0);

        return true;
      }

      // Expect a comma to follow the first element (to prove we're a tuple)
      if (!expect(Token::Type::Comma)) return false;

      // Iterate and parse each remaining element in the sequence
      if (!do_sequence(Token::Type::RightParenthesis, [&, this]() {
        // Check for a named parameter (which would make this definitely be
        // a function type)
        if (_t.peek(0)->type == Token::Type::Identifier &&
            _t.peek(1)->type == Token::Type::Colon) {
          return parse_type_function(node);
        }

        // Parse the element
        auto elem = expect(&Parser::parse_type);
        if (!elem) return false;

        // Push the element
        node->elements.push_back(elem);

        return true;
      })) return false;

      // Expect `)`
      if (!(tok = expect(Token::Type::RightParenthesis))) { return false; }
      node->span = node->span.extend(tok->span);

      // Check for a "->" (which would make this definitely be
      // a function type)
      if (_t.peek(0)->type == Token::Type::Arrow) {
        return parse_type_function(node, false);
      }

      // Push the node
      _stack.push_front(node);

      return true;
    }

    // TODO: type(X)

    // Fail; could not match a pattern
    // TODO: Should probably have shorter error message
    expect({
      Token::Type::Identifier,
      Token::Type::LeftParenthesis,
      Token::Type::Asterisk,
      Token::Type::None
    });

    return false;
  })()) { return false; }

  // Attempt to match successive `[..]` to make this an array type
  while (_t.peek()->type == Token::Type::LeftBracket) {
    _t.pop();

    // Pull the element type expression
    auto element = _stack.front();
    _stack.pop_front();

    // Check for an immediate `]` to indicate an unsized or dynamic array
    if (_t.peek()->type == Token::Type::RightBracket) {
      auto last_tok = _t.pop();

      _stack.push_front(new ast::TypeArray(
        element->span.extend(last_tok->span),
        element
      ));
    }

    // Parse an expression for the size
    if (!parse_expression()) return false;
    auto size = _stack.front();
    _stack.pop_front();

    // Expect an `]` to close the array type
    auto last_tok = expect(Token::Type::RightBracket);

    _stack.push_front(new ast::TypeArray(
      element->span.extend(last_tok->span),
      element,
      size
    ));
  }

  return true;
}
Ejemplo n.º 5
0
// Structure
// -----------------------------------------------------------------------------
// struct = [ "export" ] "struct" IDENTIFIER "{" [ struct-members ] "}" ;
// struct-members = struct-member { "," struct-member } [ "," ] ;
// struct-member = IDENTIFIER ":" type [ "=" expression ] ;
// -----------------------------------------------------------------------------
bool Parser::parse_struct() {
  // Check for "export"
  Ref<Token> initial_tok = nullptr;
  bool exported = false;
  if (_t.peek()->type == Token::Type::Export) {
    exported = true;
    initial_tok = _t.pop();
  }

  // Expect `struct`
  auto tok = expect(Token::Type::Struct);
  if (!tok) return false;
  if (!initial_tok) initial_tok = tok;

  // Expect an identifier
  auto id = expect<ast::Identifier>(&Parser::parse_identifier);
  if (!id) return false;
  auto name = id->text;

  // Expect `{`
  if (!expect(Token::Type::LeftBrace)) return false;

  // Declare the node
  Ref<ast::Structure> node = new ast::Structure(
    initial_tok->span, exported, name);

  // Iterate and parse each argument in the sequence
  if (!do_sequence(Token::Type::RightBrace, [&, this]() {
    // Expect an identifier
    auto id = expect<ast::Identifier>(&Parser::parse_identifier);
    if (!id) return false;

    // Expect `:`
    if (!expect(Token::Type::Colon)) return false;

    // Parse type annotation
    auto annotation = expect<ast::Type>(&Parser::parse_type);
    auto last_span = annotation->span;
    if (!annotation) return false;

    // Check for an `=` which would indicate a default value
    Ref<ast::Node> val = nullptr;
    if (_t.peek()->type == Token::Type::Equals) {
      _t.pop();

      if (!parse_expression()) return false;
      val = _stack.front();
      last_span = val->span;
      _stack.pop_front();
    }

    // Declare and push the member
    node->members.push_back(new ast::Member(
      id->span.extend(last_span), id->text, annotation, val));

    return true;
  })) return false;

  // Expect `}`
  if (!expect(Token::Type::RightBrace)) return false;

  // Push the node
  _stack.push_front(node);

  return true;
}