示例#1
0
/* Declare variables underneath a declarator tree */
void declare_variables_tac(environment *env, NODE *node, int variable_type, int return_type) {
	value *variable_name = NULL;
	if (env == NULL || node == NULL) {
		return;
	}
	else if (type_of(node) == ',') {
		declare_variables_tac(env, node->left, variable_type, return_type);
		declare_variables_tac(env, node->right, variable_type, return_type);
		return;		
	}
	else if (type_of(node) == '=') { /* Specific assignment */
		variable_name = make_simple(env, node->left, 0, return_type);
	}
	else if (type_of(node) == LEAF) { /* Undefined assignment */
		variable_name = make_simple(env, node->left, 0, return_type);		
	}
	/* Assign variable */
	if (variable_name) {		
		/* Assign a default initialization value for this type */
		switch(variable_type) {	
			case INT:
				assign(env, variable_name, int_value(0), 1);
				break;
			case VOID:	
				assign(env, variable_name, void_value(), 1);						
				break;
			case FUNCTION:
				assign(env, variable_name, null_fn, 1);
				break;
		}
	}
	else {
		fatal("Could not ascertain variable name!");
	}
}
示例#2
0
/* Build the correct code in the correct place for the else part */
void build_else_part(environment *env, NODE *node, int true_part, int flag, int return_type) {
	if (node==NULL || type_of(node)!=ELSE) return;
	if (true_part) {
		make_simple(env, node->left, flag, return_type);
	}
	else {
		make_simple(env, node->right, flag, return_type);		
	}
}
示例#3
0
/* Start the TAC generator process at the top of the AST */
tac_quad *start_tac_gen(NODE *tree) {
	/* Do a scan for function definitions first */
	environment *initial_env;
	initial_env = create_environment(NULL);
	null_fn = build_null_function();
	make_simple(initial_env, tree, INTERPRET_FN_SCAN, INT);
	/* Actually generate the TAC */
	make_simple(initial_env, tree, 0, 0);
	return tac_output;
}
示例#4
0
/* Build necessary code for an if statement */
void build_if_stmt(environment *env, NODE *node, int if_count, tac_quad *false_jump, tac_quad *loop_jump, int flag, int return_type) {
	char *s_tmp;
	value *val1, *val2, *temporary;
	if (node==NULL || (type_of(node)!=IF && type_of(node)!=WHILE)) return;
	/* LHS is condition */
	val1 = make_simple(env, node->left, flag, return_type);
	
	/* Generate if statement */
	s_tmp = malloc(sizeof(char) * 25);
	sprintf(s_tmp, "__if%dtrue", if_count);
	append_code(make_if(val1, s_tmp));

	/* Output false branch (i.e. else part) */	
	if (type_of(node->right)==ELSE) {
		/* Build code for false part */
		build_else_part(env, node->right, 0, flag, return_type);
	}
	
	/* Generate goto end of if statement */
	if (false_jump != NULL) {
		append_code(false_jump);
	}
	else {
		s_tmp = malloc(sizeof(char) * 25);
		sprintf(s_tmp, "__if%dend", if_count);
		append_code(make_goto(s_tmp));
	}
	
	/* Generate label for start of true branch */
	s_tmp = malloc(sizeof(char) * 25);
	sprintf(s_tmp, "__if%dtrue", if_count);
	append_code(make_label(s_tmp));
	
	/* Output true branch */
	if (type_of(node->right)==ELSE) {
		/* Build code for true part */
		build_else_part(env, node->right, 1, flag, return_type);
	}
	else {
		/* True part is whole right branch */
		make_simple(env, node->right, flag, return_type);
	}
	
	/* Check if extra loop jump has been specified (for WHILE loops etc) */
	if (loop_jump) {
		append_code(loop_jump);
	}
	
	/* Generate end of IF stmt label */
	s_tmp = malloc(sizeof(char) * 25);
	sprintf(s_tmp, "__if%dend", if_count);
	append_code(make_label(s_tmp));
}
示例#5
0
    /**
     * g forces the graph to have symmetric adjacency lists and be simple (no loops/duplicate edges) and updates flags accordingly.
     */
    void GraphProperties::make_canonical(Graph *g){
        // CSG -Should we also have g->capacity==g->num_nodes?
        make_simple(g);
        g->canonical = true;

        return;
    }
示例#6
0
static CMARK_INLINE cmark_node *make_autolink(cmark_mem *mem, cmark_chunk url,
                                              int is_email) {
  cmark_node *link = make_simple(mem, CMARK_NODE_LINK);
  link->as.link.url = cmark_clean_autolink(mem, &url, is_email);
  link->as.link.title = cmark_chunk_literal("");
  cmark_node_append_child(link, make_str_with_entities(mem, &url));
  return link;
}
示例#7
0
/* Go down the declarator tree initialising the variables, at this stage */
void register_variable_subtree_tac(environment *env, NODE *node, int return_type) {
	NODE *original_node = node;
	/* Ensure we have all required params */
	if (!env || !node || type_of(node) != '~') return;
	/* Skip over LEAF nodes */
	if (node->left != NULL && type_of(node->left) == LEAF) {
		node = node->left;
	}
	if (node->left != NULL && (type_of(node->left) == VOID || type_of(node->left) == FUNCTION || type_of(node->left) == INT)) {
		/* Find variable type */
		int variable_type = to_int(NULL, make_simple(env, node->left, 0, return_type));
		declare_variables_tac(env, original_node->right, variable_type, return_type);
	}
}
示例#8
0
// Return a link, an image, or a literal close bracket.
static cmark_node *handle_close_bracket(subject *subj) {
  bufsize_t initial_pos, after_link_text_pos;
  bufsize_t endurl, starttitle, endtitle, endall;
  bufsize_t sps, n;
  cmark_reference *ref = NULL;
  cmark_chunk url_chunk, title_chunk;
  cmark_chunk url, title;
  bracket *opener;
  cmark_node *inl;
  cmark_chunk raw_label;
  int found_label;
  cmark_node *tmp, *tmpnext;
  bool is_image;

  advance(subj); // advance past ]
  initial_pos = subj->pos;

  // get last [ or ![
  opener = subj->last_bracket;

  if (opener == NULL) {
    return make_str(subj->mem, cmark_chunk_literal("]"));
  }

  if (!opener->active) {
    // take delimiter off stack
    pop_bracket(subj);
    return make_str(subj->mem, cmark_chunk_literal("]"));
  }

  // If we got here, we matched a potential link/image text.
  // Now we check to see if it's a link/image.
  is_image = opener->image;

  after_link_text_pos = subj->pos;

  // First, look for an inline link.
  if (peek_char(subj) == '(' &&
      ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
      ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps, &url_chunk)) > -1)) {

    // try to parse an explicit link:
    endurl = subj->pos + 1 + sps + n;
    starttitle = endurl + scan_spacechars(&subj->input, endurl);

    // ensure there are spaces btw url and title
    endtitle = (starttitle == endurl)
                   ? starttitle
                   : starttitle + scan_link_title(&subj->input, starttitle);

    endall = endtitle + scan_spacechars(&subj->input, endtitle);

    if (peek_at(subj, endall) == ')') {
      subj->pos = endall + 1;

      title_chunk =
          cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
      url = cmark_clean_url(subj->mem, &url_chunk);
      title = cmark_clean_title(subj->mem, &title_chunk);
      cmark_chunk_free(subj->mem, &url_chunk);
      cmark_chunk_free(subj->mem, &title_chunk);
      goto match;

    } else {
      // it could still be a shortcut reference link
      subj->pos = after_link_text_pos;
    }
  }

  // Next, look for a following [link label] that matches in refmap.
  // skip spaces
  raw_label = cmark_chunk_literal("");
  found_label = link_label(subj, &raw_label);
  if (!found_label) {
    // If we have a shortcut reference link, back up
    // to before the spacse we skipped.
    subj->pos = initial_pos;
  }

  if ((!found_label || raw_label.len == 0) && !opener->bracket_after) {
    cmark_chunk_free(subj->mem, &raw_label);
    raw_label = cmark_chunk_dup(&subj->input, opener->position,
                                initial_pos - opener->position - 1);
    found_label = true;
  }

  if (found_label) {
    ref = cmark_reference_lookup(subj->refmap, &raw_label);
    cmark_chunk_free(subj->mem, &raw_label);
  }

  if (ref != NULL) { // found
    url = chunk_clone(subj->mem, &ref->url);
    title = chunk_clone(subj->mem, &ref->title);
    goto match;
  } else {
    goto noMatch;
  }

noMatch:
  // If we fall through to here, it means we didn't match a link:
  pop_bracket(subj); // remove this opener from delimiter list
  subj->pos = initial_pos;
  return make_str(subj->mem, cmark_chunk_literal("]"));

match:
  inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
  inl->as.link.url = url;
  inl->as.link.title = title;
  cmark_node_insert_before(opener->inl_text, inl);
  // Add link text:
  tmp = opener->inl_text->next;
  while (tmp) {
    tmpnext = tmp->next;
    cmark_node_append_child(inl, tmp);
    tmp = tmpnext;
  }

  // Free the bracket [:
  cmark_node_free(opener->inl_text);

  process_emphasis(subj, opener->previous_delimiter);
  pop_bracket(subj);

  // Now, if we have a link, we also want to deactivate earlier link
  // delimiters. (This code can be removed if we decide to allow links
  // inside links.)
  if (!is_image) {
    opener = subj->last_bracket;
    while (opener != NULL) {
      if (!opener->image) {
        if (!opener->active) {
          break;
        } else {
          opener->active = false;
        }
      }
      opener = opener->previous;
    }
  }

  return NULL;
}
示例#9
0
/* 
 * Make the given NODE simple - i.e. return a temporary for complex subtrees 
 * The appropriate code is also generated and pushed onto the code stack
*/
value *make_simple(environment *env, NODE *node, int flag, int return_type) {
	int i_value = 0;
	char *s_tmp = NULL;
	value *val1 = NULL, *val2 = NULL, *temporary = NULL, *temp = NULL;
	static int if_count = 0;
	static int while_count = 0;	
	tac_quad *temp_quad = NULL;
	environment *new_env = NULL;
	if (node==NULL) return NULL;
	switch(type_of(node)) {
		case LEAF: 
			return make_simple(env, node->left, flag, return_type);
		case CONSTANT:
			i_value = cast_from_node(node)->value;
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "%d", i_value);
			return int_value(i_value);
		case IDENTIFIER:
			return string_value(cast_from_node(node)->lexeme);
		case IF:
			build_if_stmt(env, node, ++if_count, NULL, NULL, flag, return_type);
			return NULL;
		case BREAK:
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "__while%dend", while_count);
			append_code(make_goto(s_tmp));
			return NULL;			
		case CONTINUE:
			s_tmp = malloc(sizeof(char) * 25);
			sprintf(s_tmp, "__while%d", while_count);
			append_code(make_goto(s_tmp));
			return NULL;
		case WHILE:
			build_while_stmt(env, node, ++while_count, ++if_count, flag, return_type);
			return NULL;	
		case '=':
			if (flag == INTERPRET_FN_SCAN) return NULL;
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val2 && val2->value_type!=VT_INTEGR && val2->value_type!=VT_FUNCTN) {
				if (val2->value_type == VT_STRING) {
					val2 = get(env, val2->data.string_value);
				}
				else {
					val2 = get(env, val2->identifier);
				}
				if (!val2) fatal("Undeclared identifier");					
			}
			/* Check the LHS variable has already been defined */
			temp = get(env, to_string(val1));
			assert(temp!=NULL, "Variable not defined");
			/* Type check the assignment */
			type_check_assignment(val1, val2, vt_type_convert(temp->value_type));
			temporary = assign(env, val1, val2, 0);
			if (flag != INTERPRET_FN_SCAN) append_code(make_quad_value("=", val2, NULL, temporary, TT_ASSIGN, 0));
			return NULL;
		case '*':
		case '/':
		case '>':
		case '<':										
		case '%':							
		case '-':									
		case '+':
		case NE_OP:
		case LE_OP:
		case GE_OP:				
		case EQ_OP:
			temporary = generate_temporary(env, int_value(0));
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val1->value_type==VT_STRING) val1 = get(env, correct_string_rep(val1));
			if (val2->value_type==VT_STRING) val2 = get(env, correct_string_rep(val2));
			assert(val1 != NULL, "Operand value 1 must not be null");	
			assert(val2 != NULL, "Operand value 2 must not be null");				
			if (flag != INTERPRET_FN_SCAN) append_code(make_quad_value(type_to_string(type_of(node)), val1, val2, temporary, TT_OP, type_of(node)));
			return temporary;
		case '~':
			if (flag != INTERPRET_PARAMS && flag!=INTERPRET_FN_SCAN) {
				/* Params should not be registered, because at this point we're not in the correct environment */
				register_variable_subtree_tac(env, node, VT_ANY);
			}
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (flag == INTERPRET_PARAMS) {
				return int_param(to_string(val2), to_int(env, val1));
			}			
			return NULL;
		case 'D':
			/* val1 is FN definition */
			/* val1 is executed in current environment */
			val1 = make_simple(env, node->left, flag, return_type);
			
			/* New FN body environment */
			new_env = create_environment(env);
			if (val1!=NULL) {
				/* Point function to the correct fn body */
				val1->data.func->node_value = node->right;			
				/* Store function definition in environment */
				val2 = store_function(env, val1, new_env);
			}
			if (flag != INTERPRET_FN_SCAN) {
				/* Write out FN Name label */
				append_code(make_begin_fn(val2));				
				append_code(make_fn_def(val2));
				/* Make init frame */
				temp_quad = make_init_frame();
				append_code(temp_quad);
				/* Define parameters with default empty values */
				register_params(new_env, val2->data.func->params);
				append_code(make_fn_body(val2));
				/* Look inside fn body */
				val2 = make_simple(new_env, node->right, EMBEDDED_FNS, val1->data.func->return_type);
				/* Update prepare frame with environment size */
				temp_quad->operand1 = int_value(env_size(new_env));
				/* Write end of function marker */
				append_code(make_end_fn(val2));
			}
			return NULL;
		case 'd':
			/* val1 is the type */
			val1 = make_simple(env, node->left, flag, return_type);
			/* val2 is fn name & params */
			val2 = make_simple(env, node->right, flag, return_type);
			/* Store return type */
			val2->data.func->return_type = to_int(env, val1);
			return val2;
		case 'F':
			/* FN name in val1 */
			val1 = make_simple(env, node->left, flag, return_type);
			/* Pull our parameters */
			val2 = make_simple(env, node->right, INTERPRET_PARAMS, return_type);
			return build_function(env, val1, val2);
		case RETURN:
			val1 = make_simple(env, node->left, flag, return_type);
			/* Provide lookup for non-constants */
			if (val1 && val1->value_type!=VT_INTEGR) {
				if (val1->value_type == VT_STRING) {
					val1 = get(env, val1->data.string_value);
				}
				else {
					val1 = get(env, val1->identifier);
				}
				if (!val1) fatal("Undeclared identifier");
			}
			type_check_return(val1, return_type);
			append_code(make_return(val1));
			return NULL;
		case ',':
			val1 = make_simple(env, node->left, flag, return_type);
			val2 = make_simple(env, node->right, flag, return_type);
			if (val1 && val2) {
				return join(val1, val2);
			}
			return NULL;	
		case APPLY:
			/* FN Name */
			val1 = make_simple(env, node->left, flag, return_type);
			/* Params */
			val2 = make_simple(env, node->right, flag, return_type);
			/* Lookup function */
			temp = search(env, to_string(val1), VT_FUNCTN, VT_ANY, 1);
			if (temp) {
				int fn_return_type;
				append_code(prepare_fn(val2));
				append_code(push_params(env, val2));
				/* If we can't typecheck, set a special UNDEFINED flag to say we can't */
				/* typecheck. This can happen with function variables, we do not EASILY know the */
				/* return type of the functions they are bound to until runtime. */
				fn_return_type = UNDEFINED;
				if (temp->data.func) {
					fn_return_type = temp->data.func->return_type;	
				} 
				/* Temporary for result (if any) */
				switch(fn_return_type) {
					case INT:
						temporary = generate_temporary(env, int_value(0));
						break;
					case VOID:
						temporary = generate_temporary(env, NULL);
						break;						
					case FUNCTION:
						temporary = generate_temporary(env, null_fn);
						break;
					default:
						temporary = generate_untypechecked_temporary(env);
						break;
				}
				append_code(make_fn_call(temporary, temp));
				return temporary;
			}
			else {
				fatal("Cannot find function '%s'", to_string(val1));
			}
			return NULL;
		case FUNCTION:
		case INT:
		case VOID:
			return int_value(type_of(node));
		case ';':
			make_simple(env, node->left, flag, return_type);
			make_simple(env, node->right, flag, return_type);			
			return NULL;
		default:
			fatal("Unrecognised node type");
			return NULL;
	}
}