Ejemplo n.º 1
0
static void trace_dynamic(compile_t* c, LLVMValueRef ctx, LLVMValueRef object,
  ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
      trace_dynamic_union_or_isect(c, ctx, object, type, orig, tuple,
        next_block);
      break;

    case TK_TUPLETYPE:
    {
      // This is a boxed tuple. Trace the box, then handle the elements.
      trace_tag(c, ctx, object);

      LLVMValueRef desc = gendesc_fetch(c, object);
      LLVMValueRef ptr = gendesc_ptr_to_fields(c, object, desc);
      trace_dynamic_tuple(c, ctx, ptr, desc, type, orig, tuple);
      break;
    }

    case TK_NOMINAL:
      trace_dynamic_nominal(c, ctx, object, type, orig, tuple, next_block);
      break;

    default: {}
  }
}
Ejemplo n.º 2
0
static bool static_tuple(compile_t* c, LLVMValueRef value, ast_t* type,
  ast_t* pattern, LLVMBasicBlockRef next_block)
{
  switch(ast_id(type))
  {
    case TK_UNIONTYPE:
    case TK_ISECTTYPE:
    {
      // Read the dynamic type and get a base pointer.
      LLVMValueRef desc = gendesc_fetch(c, value);
      LLVMValueRef ptr = gendesc_ptr_to_fields(c, value, desc);
      return dynamic_tuple_ptr(c, ptr, desc, pattern, next_block);
    }

    case TK_TUPLETYPE:
      return static_tuple_from_tuple(c, value, type, pattern, next_block);

    case TK_ARROW:
      return static_tuple(c, value, ast_childidx(type, 1), pattern,
        next_block);

    default: {}
  }

  // Can't match.
  LLVMBuildBr(c->builder, next_block);
  return true;
}
Ejemplo n.º 3
0
static bool dynamic_match_object(compile_t* c, LLVMValueRef object,
  LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block)
{
  switch(ast_id(pattern))
  {
    case TK_NONE:
      return true;

    case TK_MATCH_CAPTURE:
      // Capture the match expression (or element thereof).
      return dynamic_capture_object(c, object, desc, pattern, next_block);

    case TK_TUPLE:
    {
      // Treat a one element tuple as its component expression.
      ast_t* child = ast_child(pattern);

      if(ast_sibling(child) == NULL)
        return dynamic_match_object(c, object, desc, child, next_block);

      // Build a base pointer that skips the object header.
      LLVMValueRef ptr = gendesc_ptr_to_fields(c, object, desc);

      // Destructure the match expression (or element thereof).
      return dynamic_tuple_ptr(c, ptr, desc, pattern, next_block);
    }

    default:
      // Test the match expression (or element thereof).
      return dynamic_value_object(c, object, desc, pattern, next_block);
  }

  return true;
}
Ejemplo n.º 4
0
static bool check_tuple(compile_t* c, LLVMValueRef ptr, LLVMValueRef desc,
  ast_t* pattern_type, LLVMBasicBlockRef next_block)
{
  // First check cardinality.
  size_t size = ast_childcount(pattern_type);
  check_cardinality(c, desc, size, next_block);

  // If we get here, the match expression has the right cardinality.
  ast_t* pattern_child = ast_child(pattern_type);

  for(int i = 0; pattern_child != NULL; i++)
  {
    // Get the field offset and field descriptor from the tuple descriptor.
    LLVMValueRef field_info = gendesc_fieldinfo(c, desc, i);
    LLVMValueRef field_ptr = gendesc_fieldptr(c, ptr, field_info);
    LLVMValueRef field_desc = gendesc_fielddesc(c, field_info);

    // If we have a null descriptor, load the object.
    LLVMBasicBlockRef null_block = codegen_block(c, "null_desc");
    LLVMBasicBlockRef nonnull_block = codegen_block(c, "nonnull_desc");
    LLVMBasicBlockRef continue_block = codegen_block(c, "merge_desc");
    LLVMValueRef test = LLVMBuildIsNull(c->builder, field_desc, "");
    LLVMBuildCondBr(c->builder, test, null_block, nonnull_block);

    // Load the object, load its descriptor, and continue from there.
    LLVMPositionBuilderAtEnd(c->builder, null_block);
    LLVMTypeRef ptr_type = LLVMPointerType(c->object_ptr, 0);
    LLVMValueRef object_ptr = LLVMBuildIntToPtr(c->builder, field_ptr,
      ptr_type, "");
    LLVMValueRef object = LLVMBuildLoad(c->builder, object_ptr, "");
    LLVMValueRef object_desc = gendesc_fetch(c, object);
    object_ptr = gendesc_ptr_to_fields(c, object, object_desc);

    if(!check_type(c, object_ptr, object_desc, pattern_child, next_block))
      return false;

    LLVMBuildBr(c->builder, continue_block);

    // Continue with the pointer and descriptor.
    LLVMPositionBuilderAtEnd(c->builder, nonnull_block);

    if(!check_type(c, field_ptr, field_desc, pattern_child, next_block))
      return false;

    LLVMBuildBr(c->builder, continue_block);

    // Merge the two branches.
    LLVMPositionBuilderAtEnd(c->builder, continue_block);
    pattern_child = ast_sibling(pattern_child);
  }

  return true;
}
Ejemplo n.º 5
0
static bool dynamic_value_object(compile_t* c, LLVMValueRef object,
  LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block)
{
  // Get the type of the right-hand side of the pattern's eq() function.
  ast_t* param_type = eq_param_type(c, pattern);

  // Build a base pointer that skips the object header.
  LLVMValueRef ptr = gendesc_ptr_to_fields(c, object, desc);

  // Check the runtime type. We pass a pointer to the fields because we may
  // still need to match a tuple type inside a type expression.
  if(!check_type(c, ptr, desc, param_type, next_block))
    return false;

  return check_value(c, pattern, param_type, object, next_block);
}
Ejemplo n.º 6
0
static bool dynamic_capture_object(compile_t* c, LLVMValueRef object,
  LLVMValueRef desc, ast_t* pattern, LLVMBasicBlockRef next_block)
{
  ast_t* pattern_type = ast_type(pattern);

  // Build a base pointer that skips the object header.
  LLVMValueRef ptr = gendesc_ptr_to_fields(c, object, desc);

  // Check the runtime type. We pass a pointer to the fields because we may
  // still need to match a tuple type inside a type expression.
  if(!check_type(c, ptr, desc, pattern_type, next_block))
    return false;

  // As long as the type is correct, we can assign it, with gen_assign_value()
  // handling boxing and unboxing. We pass the type of the pattern as the type
  // of the object.
  return gen_assign_value(c, pattern, object, pattern_type) != NULL;
}