示例#1
0
文件: ffi.c 项目: JamesLinus/ponyc
static bool void_star_param(ast_t* param_type, ast_t* arg_type)
{
  assert(param_type != NULL);
  assert(arg_type != NULL);

  if(!is_pointer(param_type))
    return false;

  ast_t* type_args = ast_childidx(param_type, 2);

  if(ast_childcount(type_args) != 1 || !is_none(ast_child(type_args)))
    return false;

  // Parameter type is Pointer[None]
  // If the argument is Pointer[A], MaybePointer[A] or USize, allow it
  while(ast_id(arg_type) == TK_ARROW)
    arg_type = ast_childidx(arg_type, 1);

  if(is_pointer(arg_type) ||
    is_maybe(arg_type) ||
    is_literal(arg_type, "USize"))
    return true;

  return false;
}
示例#2
0
文件: data.c 项目: idkwim/radare2
R_API RAnalData *r_anal_data (RAnal *anal, ut64 addr, const ut8 *buf, int size) {
	ut64 dst = 0;
	int n, nsize = 0;
	int bits = anal->bits;
	int endi = !anal->big_endian;
	int word = R_MIN (8, bits/8);

	if (size >= word && is_invalid (buf, word))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_INVALID,
			-1, buf, word);
	if (size >= word && is_null (buf, word))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NULL,
			0, buf, word);
	if (is_bin (buf, size))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_HEADER, -1,
				buf, word);
	if (size>=word) {
		dst = is_pointer (&anal->iob, buf, endi, word);
		if (dst) return r_anal_data_new (addr,
			R_ANAL_DATA_TYPE_POINTER, dst, buf, word);
	}
	switch (is_string (buf, size, &nsize)) {
	case 1: return r_anal_data_new_string (addr, (const char *)buf,
		nsize, R_ANAL_DATA_TYPE_STRING);
	case 2: return r_anal_data_new_string (addr, (const char *)buf,
		nsize, R_ANAL_DATA_TYPE_WIDE_STRING);
	}
	if (size >= word) {
		n = is_number (buf, endi, word);
		if (n) return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NUMBER,
				n, buf, word);
	}
	return r_anal_data_new (addr, R_ANAL_DATA_TYPE_UNKNOWN, dst,
		buf, R_MIN(word, size));
}
示例#3
0
文件: genfun.c 项目: fydot/ponyc
static bool genfun_allocator(compile_t* c, gentype_t* g)
{
  // No allocator for primitive types or pointers.
  if((g->primitive != NULL) || is_pointer(g->ast))
    return true;

  const char* funname = genname_fun(g->type_name, "Alloc", NULL);
  LLVMTypeRef ftype = LLVMFunctionType(g->use_type, NULL, 0, false);
  LLVMValueRef fun = codegen_addfun(c, funname, ftype);
  codegen_startfun(c, fun, false);

  LLVMValueRef result;

  switch(g->underlying)
  {
    case TK_PRIMITIVE:
    case TK_CLASS:
      // Allocate the object or return the global instance.
      result = gencall_alloc(c, g);
      break;

    case TK_ACTOR:
      // Allocate the actor.
      result = gencall_create(c, g);
      break;

    default:
      assert(0);
      return false;
  }

  LLVMBuildRet(c->builder, result);
  codegen_finishfun(c);
  return true;
}
示例#4
0
文件: subtype.c 项目: pengzj/ponyc
// The subtype is a pointer, the supertype could be anything.
static bool is_pointer_subtype(ast_t* sub, ast_t* super)
{
  switch(ast_id(super))
  {
    case TK_NOMINAL:
    {
      // Must be a Pointer, and the type argument must be the same.
      return is_pointer(super) &&
        is_eq_typeargs(sub, super) &&
        is_sub_cap_and_ephemeral(sub, super);
    }

    case TK_TYPEPARAMREF:
    {
      // We must be a subtype of the constraint.
      ast_t* def = (ast_t*)ast_data(super);
      ast_t* constraint = ast_childidx(def, 1);

      return is_pointer_subtype(sub, constraint);
    }

    case TK_ARROW:
    {
      // We must be a subtype of the lower bounds.
      ast_t* lower = viewpoint_lower(super);
      bool ok = is_pointer_subtype(sub, lower);
      ast_free_unattached(lower);
      return ok;
    }

    default: {}
  }

  return false;
}
示例#5
0
R_API RAnalData *r_anal_data(RAnal *anal, ut64 addr, const ut8 *buf, int size) {
	ut64 dst = 0;
	int n, nsize = 0;
	int bits = anal->bits;
	int word = R_MIN (8, bits / 8);

	if (size < 4)
		return NULL;
	if (size >= word && is_invalid (buf, word))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_INVALID,
					-1, buf, word);
	{
		int i, len = R_MIN (size, 64);
		int is_pattern = 0;
		int is_sequence = 0;
		char ch = buf[0];
		char ch2 = ch + 1;
		for (i = 1; i < len; i++) {
			if (ch2 == buf[i]) {
				ch2++;
				is_sequence++;
			} else is_sequence = 0;
			if (ch == buf[i]) {
				is_pattern++;
			}
		}
		if (is_sequence > len - 2) {
			return r_anal_data_new (addr, R_ANAL_DATA_TYPE_SEQUENCE, -1,
						buf, is_sequence);
		}
		if (is_pattern > len - 2) {
			return r_anal_data_new (addr, R_ANAL_DATA_TYPE_PATTERN, -1,
						buf, is_pattern);
		}
	}
	if (size >= word && is_null (buf, word))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NULL,
					-1, buf, word);
	if (is_bin (buf, size))
		return r_anal_data_new (addr, R_ANAL_DATA_TYPE_HEADER, -1,
					buf, word);
	if (size >= word) {
		dst = is_pointer (anal, buf, word);
		if (dst) return r_anal_data_new (addr,
						R_ANAL_DATA_TYPE_POINTER, dst, buf, word);
	}
	switch (is_string (buf, size, &nsize)) {
	case 1: return r_anal_data_new_string (addr, (const char *)buf,
					nsize, R_ANAL_DATA_TYPE_STRING);
	case 2: return r_anal_data_new_string (addr, (const char *)buf,
					nsize, R_ANAL_DATA_TYPE_WIDE_STRING);
	}
	if (size >= word) {
		n = is_number (buf, word);
		if (n) return r_anal_data_new (addr, R_ANAL_DATA_TYPE_NUMBER,
					n, buf, word);
	}
	return r_anal_data_new (addr, R_ANAL_DATA_TYPE_UNKNOWN, dst,
				buf, R_MIN (word, size));
}
示例#6
0
Type Type::pointed() const {
	assert(is_pointer());
	if (_types.size() > 0) {
		return dynamic_cast<const Pointer_type*>(_types[0].get())->pointed();
	}
	assert(false && "Void type is not pointer");
}
示例#7
0
文件: subtype.c 项目: pengzj/ponyc
// The subtype is a nominal, the supertype could be anything.
static bool is_nominal_subtype(ast_t* sub, ast_t* super)
{
  // Special case Pointer[A]. It can only be a subtype of itself, because
  // in the code generator, a pointer has no vtable.
  if(is_pointer(sub))
    return is_pointer_subtype(sub, super);

  switch(ast_id(super))
  {
    case TK_NOMINAL:
      return is_nominal_sub_nominal(sub, super);

    case TK_TYPEPARAMREF:
      return is_nominal_sub_typeparam(sub, super);

    case TK_UNIONTYPE:
      return is_subtype_union(sub, super);

    case TK_ISECTTYPE:
      return is_subtype_isect(sub, super);

    case TK_ARROW:
      return is_subtype_arrow(sub, super);

    default: {}
  }

  return false;
}
示例#8
0
文件: genheader.c 项目: Preetam/ponyc
static void print_types(compile_t* c, FILE* fp, printbuf_t* buf)
{
  size_t i = HASHMAP_BEGIN;
  reachable_type_t* t;

  while((t = reachable_types_next(c->reachable, &i)) != NULL)
  {
    // Print the docstring if we have one.
    ast_t* def = (ast_t*)ast_data(t->ast);
    ast_t* docstring = ast_childidx(def, 6);

    if(ast_id(docstring) == TK_STRING)
      fprintf(fp, "/*\n%s*/\n", ast_name(docstring));

    if(!is_pointer(t->ast) && !is_maybe(t->ast) && !is_machine_word(t->ast))
    {
      // Forward declare an opaque type.
      fprintf(fp, "typedef struct %s %s;\n\n", t->name, t->name);

      // Function signature for the allocator.
      printbuf(buf,
        "/* Allocate a %s without initialising it. */\n%s* %s_Alloc();\n\n",
        t->name,
        t->name,
        t->name
        );
    }

    print_methods(c, t, buf);
  }
}
示例#9
0
void pwn::postfix_writer::do_function_call_node(pwn::function_call_node * const node, int lvl) {
  CHECK_TYPES(_compiler, _symtab, node);

  std::string id = fix_id(node->name());
  std::shared_ptr<pwn::symbol> symbol = _symtab.find(id);
  
  // put arguments in stack (reverse order)
  int args_size = 0;
  if (node->arguments()) {
    for (int i = node->arguments()->size() - 1; i >= 0; i--) {
      node->arguments()->node(i)->accept(this, lvl);
      args_size += ((cdk::expression_node *) node->arguments()->node(i))->type()->size();
    }
  }
  
  // call function
  _pf.CALL(id);
  
  // remove arguments from stack
  _pf.TRASH(args_size);
  
  // put return value in the stack
  if (is_int(symbol->type()) || is_pointer(symbol->type()) || is_string(symbol->type())) {
    _pf.PUSH();
  } else if (is_double(symbol->type())) {
    _pf.DPUSH();
  }
  
  // add this function to called functions
  _called_functions.push_back(new std::string(id));
}
示例#10
0
void pwn::postfix_writer::do_add_node(cdk::add_node * const node, int lvl) {
  CHECK_TYPES(_compiler, _symtab, node);
  
  if (is_pointer(node->type())) {
    if (is_int(node->left()->type())) {
      node->right()->accept(this, lvl + 1); // load the pointer
      node->left()->accept(this, lvl + 1); // load the shift
    } else {
      node->left()->accept(this, lvl + 1); // load the pointer
      node->right()->accept(this, lvl + 1); // load the shift
    } 
    
    _pf.INT(4); // pointer size
    _pf.MUL(); // pointer arithmetics shift calculation
    _pf.ADD();
      
    return;
  }
  
  node->left()->accept(this, lvl);
  if (is_double(node->type()) && is_int(node->left()->type())) {
    _pf.I2D();
  }
  
  node->right()->accept(this, lvl);
  if (is_double(node->type()) && is_int(node->right()->type())) {
    _pf.I2D();
  }
  
  if (is_int(node->type())) {
    _pf.ADD();    
  } else if (is_double(node->type())) {
    _pf.DADD();
  }
}
示例#11
0
static void generate_in_out_for_all()
{
	int index;
	//All in and out are empty at first
#ifdef POINTER_OPTIMIZE
	int arg_start, arg_end, arg_index, global_var_index, global_var_num  = get_globalvar_num();
	get_arg_interval(cur_func_info -> func_symt , &arg_start , &arg_end);//获得该符号表的参数开始结束标号
	for(arg_index = arg_start; arg_index <= arg_end; arg_index ++)
	{
		if(is_pointer(arg_index))
		{
			for(global_var_index = 0; global_var_index < global_var_num; global_var_index ++)
				var_list_append(pointer_in[g_block_num - 1][arg_index], global_var_index);
		}
	}

#endif

	int change = 1;
	while(change)
	{
		change = 0;
		for(index = 0; index < g_block_num; index++)
		{
			new_tmp_out();

			pointer_list_copy(tmp_out, pointer_in[index]);//just copy
			
			trans_in_to_out(DFS_array[index]);
			
			pointer_list_clear(pointer_in[index]);
			
			struct basic_block_list * list_node = DFS_array[index] -> prev;
			while(list_node != NULL)
			{
				pointer_list_merge(pointer_out[list_node -> entity-> index], pointer_in[index]);
				list_node = list_node -> next;
			}

			if(pointer_list_is_equal(tmp_out, pointer_out[index]) != 1)
			{
				change = 1;
				pointer_list_move(pointer_out[index], tmp_out);//tmp_out will be moved to pointer_out[index], and the old pointer_out[index] will be free
			}
			else
				free_tmp_out();//there will be an extra tmp_out		
#ifdef POINTER_DEBUG
			printf("block %d:\n", index);
			printf("In:");
			print_list(pointer_in[index]);
			printf("Out:");
			print_list(pointer_out[index]);
#endif	
		}
	}
#ifdef POINTER_DEBUG
	printf("\n");
#endif
}
示例#12
0
PointerWrapper::PointerWrapper(const ObjectWrapper &obj) :
  _meta_class(NULL), _address(0)
{
  kernel_assert_message(is_pointer(obj), 
			("Attempt to pointer object with non-pointer"));
  _meta_class = to<PointerMetaClass>(obj.get_meta_class());
  _address = obj.get_address();
}
示例#13
0
文件: codegen.c 项目: ras52/bootstrap
static
add_op(stream, node, is_ass, argsz) {
    auto op = node[0];

    /* Pointer plus integer needs scaling.  We canonicalised this during
     * parsing so the pointer is always the first arg which is in node[3]. */
    if ( is_pointer( node[3][2] ) && is_integral( node[4][2] ) )
        scale_elt( stream, type_size( node[3][2][3] ), 1 );
   
    if ( op == '-' || op == '-=' )
        pop_sub(stream, is_ass, argsz);
    else 
        pop_add(stream, is_ass, argsz);

    /* Pointer minus pointer needs scaling down. */
    if ( is_pointer( node[3][2] ) && is_pointer( node[4][2] ) )
        scale_elt( stream, type_size( node[3][2][3] ), -1 );
}
示例#14
0
文件: dwarf.c 项目: ozra/ponyc
void dwarf_composite(dwarf_t* dwarf, gentype_t* g)
{
  if(is_machine_word(g->ast) || is_pointer(g->ast))
    return;

  dwarf_meta_t meta;
  setup_dwarf(dwarf, &meta, g, false, false);

  symbols_composite(dwarf->symbols, &meta);
}
示例#15
0
文件: genheader.c 项目: Preetam/ponyc
static int print_pointer_type(compile_t* c, printbuf_t* buf, ast_t* type)
{
  ast_t* typeargs = ast_childidx(type, 2);
  ast_t* elem = ast_child(typeargs);

  if(is_pointer(elem) || is_maybe(elem))
    return print_pointer_type(c, buf, elem) + 1;

  print_base_type(c, buf, elem);
  return 1;
}
示例#16
0
文件: type.c 项目: NWTC/FAST_Registry
char *
assoc_or_allocated( node_t  * r )
{

   if ( is_pointer(r) ){
      return("ASSOCIATED");
   } else {
      return("ALLOCATED");
  }

}
示例#17
0
文件: genheader.c 项目: Preetam/ponyc
static void print_type_name(compile_t* c, printbuf_t* buf, ast_t* type)
{
  if(is_pointer(type) || is_maybe(type))
  {
    int depth = print_pointer_type(c, buf, type);

    for(int i = 0; i < depth; i++)
      printbuf(buf, "*");
  } else {
    print_base_type(c, buf, type);
  }
}
示例#18
0
文件: dwarf.c 项目: andymcn/ponyc
static void setup_dwarf(dwarf_t* dwarf, dwarf_meta_t* meta, gentype_t* g,
  bool opaque, bool field)
{
  memset(meta, 0, sizeof(dwarf_meta_t));

  ast_t* ast = g->ast;
  LLVMTypeRef type = g->primitive;

  if(is_machine_word(ast))
  {
    if(is_float(ast))
      meta->flags |= DWARF_FLOAT;
    else if(is_signed(dwarf->opt, ast))
      meta->flags |= DWARF_SIGNED;
    else if(is_bool(ast))
      meta->flags |= DWARF_BOOLEAN;
  }
  else if(is_pointer(ast) || is_maybe(ast) || !is_concrete(ast) ||
    (is_constructable(ast) && field))
  {
    type = g->use_type;
  }
  else if(is_constructable(ast))
  {
    type = g->structure;
  }

  bool defined_type = g->underlying != TK_TUPLETYPE &&
    g->underlying != TK_UNIONTYPE && g->underlying != TK_ISECTTYPE;

  source_t* source;

  if(defined_type)
    ast = (ast_t*)ast_data(ast);

  source = ast_source(ast);
  meta->file = source->file;
  meta->name = g->type_name;
  meta->line = ast_line(ast);
  meta->pos = ast_pos(ast);

  if(!opaque)
  {
    meta->size = LLVMABISizeOfType(dwarf->target_data, type) << 3;
    meta->align = LLVMABIAlignmentOfType(dwarf->target_data, type) << 3;
  }
}
示例#19
0
文件: mclang.cpp 项目: monkin/img_cl
	const std::string &Type::name() const {
		auto i = names.find(type_id);
		if(i!=names.end())
			return i->second;
		else if(is_vector()) {
			std::stringstream s;
			s << vector_of().name() << vector_size();
			names.insert(std::pair<int, std::string>(type_id, s.str()));
			return names[type_id];
		} else if(is_pointer()) {
			std::stringstream s;
			s << "__global " << pointer_to().name() << " *";
			names.insert(std::pair<int, std::string>(type_id, s.str()));
			return names[type_id];
		} else {
			assert(!"Invalid type.");
		}
	}
示例#20
0
LLVMValueRef gencall_alloc(compile_t* c, reach_type_t* t)
{
  // Do nothing for primitives.
  if(t->primitive != NULL)
    return NULL;

  // Do nothing for Pointer and Maybe.
  if(is_pointer(t->ast) || is_maybe(t->ast))
    return NULL;

  // Use the global instance if we have one.
  if(t->instance != NULL)
    return t->instance;

  if(t->underlying == TK_ACTOR)
    return gencall_create(c, t);

  return gencall_allocstruct(c, t);
}
示例#21
0
static bool call_needs_receiver(ast_t* postfix, reach_type_t* t)
{
  switch(ast_id(postfix))
  {
    case TK_NEWREF:
    case TK_NEWBEREF:
      break;

    default:
      return true;
  }

  // No receiver if a new primitive.
  if(t->primitive != NULL)
    return false;

  // No receiver if a new Pointer or Maybe.
  if(is_pointer(t->ast) || is_maybe(t->ast))
    return false;

  return true;
}
示例#22
0
文件: gencall.c 项目: Theodus/ponyc
static bool call_needs_receiver(ast_t* postfix, reach_type_t* t)
{
  switch(ast_id(postfix))
  {
    case TK_NEWREF:
    case TK_NEWBEREF:
      // No receiver if a new primitive.
      if(((compile_type_t*)t->c_type)->primitive != NULL)
        return false;

      // No receiver if a new Pointer or Maybe.
      if(is_pointer(t->ast) || is_maybe(t->ast))
        return false;

      return true;

    // Always generate the receiver, even for bare function calls. This ensures
    // that side-effects always happen.
    default:
      return true;
  }
}
示例#23
0
文件: subtype.c 项目: pengzj/ponyc
bool is_composite(ast_t* type)
{
  return !is_machine_word(type) && !is_pointer(type);
}
示例#24
0
static int is_nullptr(struct var val)
{
    return 
        (is_integer(val.type) || is_pointer(val.type)) &&
        (val.kind == IMMEDIATE && !val.imm.u);
}
示例#25
0
void LuaStack::check_temporary(int i, const Matrix4x4* p)
{
	LuaEnvironment* env = device()->lua_environment();
	if (!is_pointer(i) || !env->is_matrix4x4(p))
		luaL_typerror(L, i, "Matrix4x4");
}
示例#26
0
void LuaStack::check_temporary(int i, const Vector3* p)
{
	LuaEnvironment* env = device()->lua_environment();
	if (!is_pointer(i) || !env->is_vector3(p))
		luaL_typerror(L, i, "Vector3");
}
示例#27
0
void pwn::postfix_writer::do_variable_declaration_node(pwn::variable_declaration_node * const node, int lvl) {
  CHECK_TYPES(_compiler, _symtab, node);
  
  std::string id = fix_id(node->name());
  bool initialize = node->initial_value() != nullptr; 
  std::shared_ptr<pwn::symbol> symbol = _symtab.find(id);
  
  if (_current_function) 
  { // local scope
    if (node->is_local() || node->is_import()) {
      throw "It's not allowed to use local or import keywords in blocks.";
    }
    
    if (_current_offset >= 8) {
      // function arguments
      if (initialize) {
        throw "Error: function arguments cannot be initialized.";
      }
      symbol->offset(_current_offset);
      _current_offset += node->type()->size();
    } else if (_current_offset <= 0) {
      // local variables
      _current_offset -= node->type()->size();
      symbol->offset(_current_offset);
      if (initialize) {
        node->initial_value()->accept(this, lvl);
        _pf.LOCAL(symbol->offset());
        
        basic_type *var_type = node->type();
        if (is_int(var_type) || is_string(var_type) || is_pointer(var_type)) {
          _pf.STORE();
        } else if (is_double(var_type)) {
          _pf.DSTORE();
        }
      } // end initialize
    } else {
      throw "Error: bad offset.";
    }
    
  } // end local scope
  else 
  { // global scope 
    if (node->is_import()) {
      _pf.EXTERN(id);
      return; // nothing else to do.
    }
    
    // Choose segment
    if (initialize) {
      _pf.DATA();
    } else {
      _pf.BSS();
    }
    
    if ( ! node->is_local()) {
      _pf.GLOBAL(node->name(), _pf.OBJ());
    }
      
    if (initialize) {
      _current_id = &id;
      node->initial_value()->accept(this, lvl);
    } else {
      _pf.ALIGN();
      _pf.LABEL(id);
      _pf.BYTE(node->type()->size());
    }
  } // end global scope
  
}
示例#28
0
void pwn::postfix_writer::do_function_definition_node(pwn::function_definition_node * const node, int lvl) {
  CHECK_TYPES(_compiler, _symtab, node);

  _current_function_end = ++_lbl;

  _pf.TEXT();
  _pf.ALIGN();
  std::string name = fix_id(node->name());
  
  // is global ?
  if ( ! node->is_local()) {
    _pf.GLOBAL(name, _pf.FUNC());    
  }
  
  _pf.LABEL(name);
  
  // find space needed for local variables
  pwn::enter_size *visitor = new pwn::enter_size(_compiler);
  node->accept(visitor, 0);
  int size = visitor->size();
  delete visitor;
  
  // reserve memory
  _pf.ENTER(size);

  // set current function
  _current_function = _symtab.find_local(node->name());
  
  // create new context
  _symtab.push();

  if (node->arguments()) {
    _current_offset = 8;  // function arguments offset
    node->arguments()->accept(this, lvl + 1);
  }
  
  _current_offset = 0; // local variables offset
  
  // reserve space for return variable
  int return_size = 0;
  if (is_int(node->return_type()) || is_string(node->return_type()) || is_pointer(node->return_type())) {
    return_size = 4; // int, string, pointer
  } else if (is_double(node->return_type())) {
    return_size = 8; // double
  }
  
  _current_offset -= return_size;
  
  // handle default return value
  if (node->return_default()) {
    node->return_default()->accept(this, lvl + 1);
    if (return_size == 4) {
      _pf.LOCA(-4);
    } else if (return_size == 8) {
      _pf.LOCAL(-8);
      _pf.DSTORE();
    }
  } else {
    // if no return default is specified, return 0 if int or pointer
    _pf.INT(0);
    _pf.LOCA(-4);
  }
  
  // function body
  node->block()->accept(this, lvl);
  
  _pf.ALIGN();
  _pf.LABEL(mklbl(_current_function_end));

  // put return value in eax
  if (return_size == 4) {
    // int string pointer
    _pf.LOCV(-4);
    _pf.POP();
  } else if (return_size == 8) {
    // double
    _pf.LOCAL(-8);
    _pf.DLOAD();
    _pf.DPOP();
  }

  // return from function
  _pf.LEAVE();
  _pf.RET();
  
  // leave local context
  _symtab.pop(); 
  _current_function = nullptr;

  // add this function to defined functions list
  _defined_functions.push_back(new std::string(name));
}
示例#29
0
bool expr_nominal(pass_opt_t* opt, ast_t** astp)
{
  // Resolve type aliases and typeparam references.
  if(!names_nominal(opt, *astp, astp, true))
    return false;

  ast_t* ast = *astp;

  switch(ast_id(ast))
  {
    case TK_TYPEPARAMREF:
      return flatten_typeparamref(opt, ast) == AST_OK;

    case TK_NOMINAL:
      break;

    default:
      return true;
  }

  // If still nominal, check constraints.
  ast_t* def = (ast_t*)ast_data(ast);

  // Special case: don't check the constraint of a Pointer or an Array. These
  // builtin types have no contraint on their type parameter, and it is safe
  // to bind a struct as a type argument (which is not safe on any user defined
  // type, as that type might then be used for pattern matching).
  if(is_pointer(ast) || is_literal(ast, "Array"))
    return true;

  ast_t* typeparams = ast_childidx(def, 1);
  ast_t* typeargs = ast_childidx(ast, 2);

  if(!reify_defaults(typeparams, typeargs, true, opt))
    return false;

  if(is_maybe(ast))
  {
    // MaybePointer[A] must be bound to a struct.
    assert(ast_childcount(typeargs) == 1);
    ast_t* typeparam = ast_child(typeparams);
    ast_t* typearg = ast_child(typeargs);
    bool ok = false;

    switch(ast_id(typearg))
    {
      case TK_NOMINAL:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = ast_id(def) == TK_STRUCT;
        break;
      }

      case TK_TYPEPARAMREF:
      {
        ast_t* def = (ast_t*)ast_data(typearg);
        ok = def == typeparam;
        break;
      }

      default: {}
    }

    if(!ok)
    {
      ast_error(opt->check.errors, ast,
        "%s is not allowed: "
        "the type argument to MaybePointer must be a struct",
        ast_print_type(ast));

      return false;
    }

    return true;
  }

  return check_constraints(typeargs, typeparams, typeargs, true, opt);
}
示例#30
0
void LuaStack::check_temporary(int i, const Quaternion* p)
{
	LuaEnvironment* env = device()->lua_environment();
	if (!is_pointer(i) || !env->is_quaternion(p))
		luaL_typerror(L, i, "Quaternion");
}