📄 compile.c
字号:
LIST *compile_local( PARSE *parse, FRAME *frame ){ LIST *l; SETTINGS *s = 0; LIST *nt = parse_evaluate( parse->left, frame ); LIST *ns = parse_evaluate( parse->right, frame ); LIST *result; if( DEBUG_COMPILE ) { debug_compile( 0, "local", frame); list_print( nt ); printf( " = " ); list_print( ns ); printf( "\n" ); } /* Initial value is ns */ for( l = nt; l; l = list_next( l ) ) s = addsettings( s, VAR_SET, l->string, list_copy( (LIST*)0, ns ) ); list_free( ns ); list_free( nt ); /* Note that callees of the current context get this "local" */ /* variable, making it not so much local as layered. */ pushsettings( s ); result = parse_evaluate( parse->third, frame ); popsettings( s ); freesettings( s ); return result;}/* * compile_null() - do nothing -- a stub for parsing */LIST *compile_null( PARSE *parse, FRAME *frame ){ return L0;}/* * compile_on() - run rule under influence of on-target variables * * parse->left list of files to include (can only do 1) * parse->right rule to run * * EXPERIMENTAL! */LIST *compile_on( PARSE *parse, FRAME *frame ){ LIST *nt = parse_evaluate( parse->left, frame ); LIST *result = 0; if( DEBUG_COMPILE ) { debug_compile( 0, "on", frame ); list_print( nt ); printf( "\n" ); } if( nt ) { TARGET *t = bindtarget( nt->string ); pushsettings( t->settings ); result = parse_evaluate( parse->right, frame ); popsettings( t->settings ); } list_free( nt ); return result;}/* * compile_rule() - compile a single user defined rule * * parse->string name of user defined rule * parse->left parameters (list of lists) to rule, recursing left * * Wrapped around evaluate_rule() so that headers() can share it. */LIST *compile_rule( PARSE *parse, FRAME *frame ){ FRAME inner[1]; LIST *result; PARSE *p; /* Build up the list of arg lists */ frame_init( inner ); inner->prev = frame; inner->prev_user = frame->module->user_module ? frame : frame->prev_user; inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below */ inner->procedure = parse; for( p = parse->left; p; p = p->left ) lol_add( inner->args, parse_evaluate( p->right, frame ) ); /* And invoke rule */ result = evaluate_rule( parse->string, inner ); frame_free( inner ); return result;}static void argument_error( char* message, RULE* rule, FRAME* frame, LIST* arg ){ LOL* actual = frame->args; assert( frame->procedure != 0 ); backtrace_line( frame->prev ); printf( "*** argument error\n* rule %s ( ", frame->rulename ); lol_print( rule->arguments->data ); printf( " )\n* called with: ( " ); lol_print( actual ); printf( " )\n* %s %s\n", message, arg ? arg->string : "" ); print_source_line( rule->procedure ); printf( "see definition of rule '%s' being called\n", rule->name ); backtrace( frame->prev ); exit(1);}/* define delimiters for type check elements in argument lists (and * return type specifications, eventually) */# define TYPE_OPEN_DELIM '['# define TYPE_CLOSE_DELIM ']'/* is_type_name - true iff the given string represents a type check * specification */static intis_type_name( char* s ){ return s[0] == TYPE_OPEN_DELIM && s[strlen(s) - 1] == TYPE_CLOSE_DELIM;}/* * arg_modifier - if the next element of formal is a single character, * return that; return 0 otherwise. Used to extract "*+?" modifiers * from argument lists. */static chararg_modifier( LIST* formal ){ if ( formal->next ) { char *next = formal->next->string; if ( next && next[0] != 0 && next[1] == 0 ) return next[0]; } return 0;}/* * type_check - checks that each element of values satisfies the * requirements of type_name. * * caller - the frame of the rule calling the rule whose * arguments are being checked * * called - the rule being called * * arg_name - a list element containing the name of the argument * being checked */static voidtype_check( char* type_name, LIST *values, FRAME* caller, RULE* called, LIST* arg_name ){ static module_t *typecheck = 0; /* if nothing to check, bail now */ if ( !values || !type_name ) return; if ( !typecheck ) typecheck = bindmodule(".typecheck"); /* if the checking rule can't be found, also bail */ { RULE checker_, *checker = &checker_; checker->name = type_name; if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA**)&checker ) ) return; } exit_module( caller->module ); while ( values != 0 ) { LIST *error; FRAME frame[1]; frame_init( frame ); frame->module = typecheck; frame->prev = caller; frame->prev_user = caller->module->user_module ? caller : caller->prev_user; enter_module( typecheck ); /* Prepare the argument list */ lol_add( frame->args, list_new( L0, values->string ) ); error = evaluate_rule( type_name, frame ); exit_module( typecheck ); if ( error ) argument_error( error->string, called, caller, arg_name ); frame_free( frame ); values = values->next; } enter_module( caller->module );}/* * collect_arguments() - local argument checking and collection */static SETTINGS *collect_arguments( RULE* rule, FRAME* frame ){ SETTINGS *locals = 0; LOL* all_actual = frame->args; LOL *all_formal = rule->arguments ? rule->arguments->data : 0; if ( all_formal ) /* Nothing to set; nothing to check */ { int max = all_formal->count > all_actual->count ? all_formal->count : all_actual->count; int n; for ( n = 0; n < max ; ++n ) { LIST *actual = lol_get( all_actual, n ); char *type_name = 0; LIST *formal; for ( formal = lol_get( all_formal, n ); formal; formal = formal->next ) { char* name = formal->string; if ( is_type_name(name) ) { if ( type_name ) argument_error( "missing argument name before type name:", rule, frame, formal ); if ( !formal->next ) argument_error( "missing argument name after type name:", rule, frame, formal ); type_name = formal->string; } else { LIST* value = 0; char modifier; LIST* arg_name = formal; /* hold the argument name for type checking */ /* Stop now if a variable number of arguments are specified */ if ( name[0] == '*' && name[1] == 0 ) return locals; modifier = arg_modifier( formal ); if ( !actual && modifier != '?' && modifier != '*' ) argument_error( "missing argument", rule, frame, formal ); switch ( modifier ) { case '+': case '*': value = list_copy( 0, actual ); actual = 0; /* skip an extra element for the modifier */ formal = formal->next; break; case '?': /* skip an extra element for the modifier */ formal = formal->next; /* fall through */ default: if ( actual ) /* in case actual is missing */ { value = list_new( 0, actual->string ); actual = actual->next; } } locals = addsettings( locals, VAR_SET, name, value ); type_check( type_name, value, frame, rule, arg_name ); type_name = 0; } } if ( actual ) { argument_error( "extra argument", rule, frame, actual ); } } } return locals;}static int python_instance_number = 0;RULE *enter_rule( char *rulename, module_t *target_module );#ifdef HAVE_PYTHONstatic LIST*call_python_function(RULE* r, FRAME* frame){ LIST* result = 0; PyObject* arguments = PyTuple_New(frame->args->count); int i ; PyObject* py_result; for(i = 0; i < frame->args->count; ++i) { PyObject* arg = PyList_New(0); LIST* l = lol_get( frame->args, i); for(; l; l = l->next) { PyObject* v = PyString_FromString(l->string); /* Steals reference to 'v' */ PyList_Append(arg, v); } /* Steals reference to 'arg' */ PyTuple_SetItem(arguments, i, arg); } frame_before_python_call = frame; py_result = PyObject_CallObject(r->python_function, arguments); Py_DECREF(arguments); if (py_result != NULL) { if (PyList_Check(py_result)) { int size = PyList_Size(py_result); int i; for(i = 0; i < size; ++i) { PyObject* item = PyList_GetItem(py_result, i); if (PyString_Check(item)) { result = list_new(result, newstr(PyString_AsString(item))); } else { fprintf(stderr, "Non-string object returned by Python call\n"); } } } else if (PyInstance_Check(py_result)) { static char instance_name[1000]; static char imported_method_name[1000]; module_t* m; PyObject* method; PyObject* method_name = PyString_FromString("foo"); RULE* r; fprintf(stderr, "Got instance!\n"); snprintf(instance_name, 1000, "pyinstance%d", python_instance_number); snprintf(imported_method_name, 1000, "pyinstance%d.foo", python_instance_number); ++python_instance_number; m = bindmodule(instance_name); /* This is expected to get bound method. */ method = PyObject_GetAttr(py_result, method_name); r = bindrule( imported_method_name, root_module() ); r->python_function = method; result = list_new(0, newstr(instance_name)); Py_DECREF(method_name); } else if (py_result == Py_None) { result = L0; } else { fprintf(stderr, "Non-list object returned by Python call\n"); } Py_DECREF(py_result); } else { PyErr_Print(); fprintf(stderr,"Call failed\n"); } return result;}module_t* python_module(){ static module_t* python = 0; if ( !python ) python = bindmodule("__python__"); return python;}#endif/* * evaluate_rule() - execute a rule invocation */LIST *evaluate_rule( char *rulename, FRAME *frame ){ LIST *result = L0; RULE *rule; profile_frame prof[1]; module_t *prev_module = frame->module; LIST *l; { LOL arg_context_, *arg_context = &arg_context_; if ( !frame->prev ) lol_init(arg_context); else arg_context = frame->prev->args; l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 ); } if ( !l ) { backtrace_line( frame->prev ); printf( "warning: rulename %s expands to empty string\n", rulename ); backtrace( frame->prev ); return result; } rulename = l->string;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -