--- metal/metal_class.php 2001/04/16 02:59:20 1.42 +++ metal/metal_class.php 2001/12/08 04:24:32 1.74 @@ -6,7 +6,7 @@ if(!defined("METAL_CLASS_INCLUDED")) /* * metal_class.php * - * @(#) $Header: /opt2/mlemos/cvs/metal/metal/metal_class.php,v 1.42 2001/04/16 02:59:20 mlemos Exp $ + * @(#) $Header: /opt2/mlemos/cvs/metal/metal/metal_class.php,v 1.74 2001/12/08 04:24:32 mlemos Exp $ * */ @@ -16,6 +16,63 @@ class metal_class_class extends metal_ba var $subclasses=array(); var $current_class=0; var $current_function=""; + var $current_argument=""; + var $current_argument_number=0; + var $current_variable=""; + var $current_subclass=0; + + Function GetDocumentation(&$scope,&$compiler,&$code,&$attributes,$element_path) + { + Unset($idiom); + $documentation=array(); + $documentation_elements=$code->structure[$element_path]["Elements"]; + for($documentation_element=0;$documentation_element<$documentation_elements;$documentation_element++) + { + $documentation_element_path=$element_path.",$documentation_element"; + $data=$code->structure[$documentation_element_path]; + if(GetType($data)=="array") + { + switch($data["Tag"]) + { + case "idiom": + if(IsSet($idiom)) + { + $compiler->SetElementError($attributes->file,$documentation_element_path,"it was defined the documentation idiom more than once"); + return(0); + } + if(!$compiler->GetValidName($attributes->file,$documentation_element_path,&$idiom,"it was not specified a valid class documentation idiom option")) + return(0); + if(IsSet($scope["documentation"][$idiom])) + { + $compiler->SetElementError($attributes->file,$documentation_element_path,"it was specified the idiom of an already defined class documentation section"); + return(0); + } + break; + default: + if(IsSet($documentation[$data["Tag"]])) + { + $compiler->SetElementError($attributes->file,$documentation_element_path,"it was specified the documentation tag ".$data["Tag"]." more than once"); + return(0); + } + $compiler->CopyEmptyContext(&$attributes,&$documentation[$data["Tag"]]); + $documentation[$data["Tag"]]->path=$documentation_element_path; + break; + } + } + else + { + if(!$compiler->CheckWhiteSpace($attributes->file,$data,$documentation_element_path)) + return(0); + } + } + if(!IsSet($idiom)) + { + $compiler->SetElementError($attributes->file,$element_path,"it was not defined the class documentation idiom"); + return(0); + } + $scope["documentation"][$idiom]=$documentation; + return(1); + } Function SetupClass(&$compiler,&$code,&$attributes) { @@ -24,6 +81,7 @@ class metal_class_class extends metal_ba $this->classes[$index]["return_type"]=""; $this->classes[$index]["return_value_set"]=0; $this->classes[$index]["staticload"]=0; + $this->classes[$index]["types"]=array(); $this->classes[$index]["functions"]=array(); $this->classes[$index]["variables"]=array(); $this->classes[$index]["declarationfile"]=$attributes->file; @@ -124,6 +182,8 @@ class metal_class_class extends metal_ba $function["type"]=$this->classes[$class_parent]["functions"][$name]["type"]; if(IsSet($this->classes[$class_parent]["functions"][$name]["Arguments"])) $function["Arguments"]=$this->classes[$class_parent]["functions"][$name]["Arguments"]; + if(IsSet($this->classes[$class_parent]["functions"][$name]["protected"])) + $function["protected"]=$this->classes[$class_parent]["functions"][$name]["protected"]; break; } if(!IsSet($this->classes[$class_parent]["parent"])) @@ -155,16 +215,36 @@ class metal_class_class extends metal_ba case "VOID": case "STRING": case "INTEGER": + case "FLOAT": case "BOOLEAN": case "OBJECT": case "ARRAY": - case "ASSOCIATIVEARRAY": + case "HASH": break; default: $compiler->SetElementError($attributes->file,$function_element_path,"it was not defined a valid class function return type"); return(0); } break; + case "protected": + if(!IsSet($name)) + { + $compiler->SetElementError($attributes->file,$function_element_path,"it was defined the class function protected status before specifying its name"); + return(0); + } + if($index + && IsSet($this->classes[$parent]["functions"][$name])) + { + $compiler->SetElementError($attributes->file,$function_element_path,"it was attempted to redefine the class protected status of a inherited subclass function"); + return(0); + } + if(IsSet($function["protected"])) + { + $compiler->SetElementError($attributes->file,$function_element_path,"it was defined the class function protected status more than once"); + return(0); + } + $function["protected"]=1; + break; case "argument": if(!IsSet($name)) { @@ -214,25 +294,66 @@ class metal_class_class extends metal_ba { case "STRING": case "INTEGER": + case "FLOAT": case "BOOLEAN": case "OBJECT": case "ARRAY": - case "ASSOCIATIVEARRAY": + case "HASH": break; default: $compiler->SetElementError($attributes->file,$argument_element_path,"it was not defined a valid class function argument type"); return(0); } break; - case "reference": - if(IsSet($argument["reference"])) + case "defaultvalue": + if(IsSet($argument["defaultvalue"])) + { + $compiler->SetElementError($attributes->file,$argument_element_path,"it was defined the class function argument defaultvalue more than once"); + return(0); + } + if(IsSet($argument["parameter"])) + { + switch($argument["parameter"]) + { + case "out": + case "inout": + $compiler->SetElementError($attributes->file,$argument_element_path,"it was defined a defaultvalue for a class function argument to be passed as ".$argument["parameter"]); + return(0); + } + } + if(!IsSet($argument["type"])) + { + $compiler->SetElementError($attributes->file,$argument_element_path,"it was not defined the class function argument type before defining the defaultvalue"); + return(0); + } + if(!$compiler->GetValidData($attributes->file,$argument_element_path,&$argument["defaultvalue"],"it was not specified a valid class argument defaultvalue option") + || !$compiler->ConvertData(&$attributes,$argument["type"],$argument["defaultvalue"],&$argument["converteddefaultvalue"])) + return(0); + break; + case "in": + case "out": + case "inout": + if(IsSet($argument["parameter"])) { - $compiler->SetElementError($attributes->file,$argument_element_path,"it was defined the class function argument reference more than once"); + $compiler->SetElementError($attributes->file,$argument_element_path,"class function argument is already defined as ".$argument["parameter"]); return(0); } - $argument["reference"]=1; + switch($data["Tag"]) + { + case "out": + case "inout": + if(IsSet($argument["defaultvalue"])) + { + $compiler->SetElementError($attributes->file,$argument_element_path,"it was defined a defaultvalue for a ".$data["Tag"]." class function argument"); + return(0); + } + break; + } + $argument["parameter"]=$data["Tag"]; break; case "documentation": + if(!$this->GetDocumentation(&$argument,&$compiler,&$code,&$attributes,$argument_element_path)) + return(0); break; default: $compiler->SetElementError($attributes->file,$argument_element_path,$data["Tag"]." is not a supported class function argument attribute"); @@ -255,6 +376,8 @@ class metal_class_class extends metal_ba $compiler->SetElementError($attributes->file,$function_element_path,"it was not defined the class function argument type"); return(0); } + if(!IsSet($argument["parameter"])) + $argument["parameter"]="in"; $function["Arguments"][$argument_name]=$argument; break; case "do": @@ -270,6 +393,8 @@ class metal_class_class extends metal_ba $this->classes[$index]["functions"][$name]=$function; break; case "documentation": + if(!$this->GetDocumentation(&$function,&$compiler,&$code,&$attributes,$function_element_path)) + return(0); break; default: $compiler->SetElementError($attributes->file,$function_element_path,$data["Tag"]." is not a supported class object attribute"); @@ -330,7 +455,11 @@ class metal_class_class extends metal_ba } if($index && IsSet($this->classes[$parent]["variables"][$name])) + { $variable["type"]=$this->classes[$parent]["variables"][$name]["type"]; + if(IsSet($this->classes[$parent]["variables"][$name]["protected"])) + $variable["protected"]=$this->classes[$parent]["variables"][$name]["protected"]; + } break; case "type": if(!IsSet($name)) @@ -355,16 +484,36 @@ class metal_class_class extends metal_ba { case "STRING": case "INTEGER": + case "FLOAT": case "BOOLEAN": case "OBJECT": case "ARRAY": - case "ASSOCIATIVEARRAY": + case "HASH": break; default: $compiler->SetElementError($attributes->file,$variable_element_path,"it was not defined a valid class variable type"); return(0); } break; + case "protected": + if(!IsSet($name)) + { + $compiler->SetElementError($attributes->file,$variable_element_path,"it was defined the class variable protected status before specifying its name"); + return(0); + } + $class=$parent; + if($this->InheritedVariableClass(&$class,$name)) + { + $compiler->SetElementError($attributes->file,$variable_element_path,"it was attempted to redefine the protected status of a inherited subclass variable"); + return(0); + } + if(IsSet($variable["protected"])) + { + $compiler->SetElementError($attributes->file,$variable_element_path,"it was defined the class variable protected status more than once"); + return(0); + } + $variable["protected"]=1; + break; case "value": $class=$parent; if($this->InheritedVariableClass(&$class,$name)) @@ -384,10 +533,12 @@ class metal_class_class extends metal_ba return(0); } if(!$compiler->GetValidData($attributes->file,$variable_element_path,&$variable["value"],"it was not specified a valid class variable value option") - || !$compiler->ConvertData(&$attributes,$type,$variable["value"],&$variable["value"])) + || !$compiler->ConvertData(&$attributes,$type,$variable["value"],&$variable["convertedvalue"])) return(0); break; case "documentation"; + if(!$this->GetDocumentation(&$variable,&$compiler,&$code,&$attributes,$variable_element_path)) + return(0); break; default: $compiler->SetElementError($attributes->file,$variable_element_path,$data["Tag"]." is not a supported class object variable attribute"); @@ -414,10 +565,14 @@ class metal_class_class extends metal_ba } $this->classes[$index]["variables"][$name]=$variable; break; + case "abstract": + $this->classes[$index][$data["Tag"]]=1; + break; case "file": case "basepath": case "tag": - case "comment": + case "version": + case "copyright": case "title": case "author": case "authoraddress": @@ -425,54 +580,8 @@ class metal_class_class extends metal_ba return(0); break; case "documentation": - Unset($idiom); - $documentation=array(); - $documentation_elements=$code->structure[$element_path]["Elements"]; - for($documentation_element=0;$documentation_element<$documentation_elements;$documentation_element++) - { - $documentation_element_path=$element_path.",$documentation_element"; - $data=$code->structure[$documentation_element_path]; - if(GetType($data)=="array") - { - switch($data["Tag"]) - { - case "idiom": - if(IsSet($idiom)) - { - $compiler->SetElementError($attributes->file,$documentation_element_path,"it was defined the documentation idiom more than once"); - return(0); - } - if(!$compiler->GetValidName($attributes->file,$documentation_element_path,&$idiom,"it was not specified a valid class documentation idiom option")) - return(0); - if(IsSet($this->classes[$index]["documentation"][$idiom])) - { - $compiler->SetElementError($attributes->file,$documentation_element_path,"it was specified the idiom of an already defined class documentation section"); - return(0); - } - break; - default: - if(IsSet($documentation[$data["Tag"]])) - { - $compiler->SetElementError($attributes->file,$documentation_element_path,"it was specified the documentation tag ".$data["Tag"]." more than once"); - return(0); - } - $compiler->CopyEmptyContext(&$attributes,&$documentation[$data["Tag"]]); - $documentation[$data["Tag"]]->path=$documentation_element_path; - break; - } - } - else - { - if(!$compiler->CheckWhiteSpace($attributes->file,$data,$documentation_element_path)) - return(0); - } - } - if(!IsSet($idiom)) - { - $compiler->SetElementError($attributes->file,$element_path,"it was not defined the class documentation idiom"); + if(!$this->GetDocumentation(&$this->classes[$index],&$compiler,&$code,&$attributes,$element_path)) return(0); - } - $this->classes[$index]["documentation"][$idiom]=$documentation; break; default: $compiler->SetElementError($attributes->file,$element_path,$data["Tag"]." is not a supported class object class attribute"); @@ -499,7 +608,15 @@ class metal_class_class extends metal_ba } } if($index) + { + if(IsSet($this->classes[$index]["abstract"]) + && !IsSet($this->classes[$parent]["abstract"])) + { + $compiler->SetElementError($attributes->file,$attributes->path,"it was defined the abstract attribute for a subclass of a class that is not abstract"); + return(0); + } $this->classes[$index]["parent"]=$parent; + } if(!IsSet($this->classes[$index]["tag"])) $this->classes[$index]["tag"]="CLASS_".strtoupper(ereg_replace("[^A-Za-z0-9]","_",$this->classes[$index]["file"])); return(1); @@ -541,6 +658,53 @@ class metal_class_class extends metal_ba return(1); } + Function GenerateFunction(&$compiler,$class,$name) + { + if(!IsSet($this->classes[$class]["functions"][$name]["do"]["code"])) + { + $this->classes[$class]["functions"][$name]["do"]["code"]=array(); + $function_name=$this->classes[$class]["function_name"]; + $return_type=$this->classes[$class]["return_type"]; + $return_value_set=$this->classes[$class]["return_value_set"]; + $this->classes[$class]["function_name"]=$name; + $this->classes[$class]["return_type"]=$this->classes[$class]["functions"][$name]["type"]; + $this->classes[$class]["return_value_set"]=0; + $action_context=new metal_execution_context_class; + $action_context->file=$this->classes[$class]["functions"][$name]["do"]["file"]; + $action_context->path=$this->classes[$class]["functions"][$name]["do"]["path"]; + $action_context->result=array(); + $functions=array( + "instancevariable", + "instancecall", + "functionargument", + "return" + ); + if(!$compiler->AddContextFunctions(&$action_context,$this->object_name,&$functions,&$level) + || !$compiler->StartScope(&$action_context,&$scope,"method")) + return(0); + $current_subclass=$this->current_subclass; + $this->current_subclass=$class; + if(!$compiler->GetOutputData($this->classes[$class]["functions"][$name]["do"]["file"],$this->classes[$class]["functions"][$name]["do"]["path"],&$this->classes[$class]["functions"][$name]["do"]["code"],"it were not defined valid class function do statements",1) + || !$compiler->GetScopeVariables(&$context,$scope,&$this->classes[$class]["functions"][$name]["variables"])) + return(0); + $this->current_subclass=$current_subclass; + $success=$compiler->EndScope(&$action_context,$scope); + if(!$compiler->RemoveContextFunctions(&$action_context,$this->object_name,$level) + || !$success) + return(0); + if(strcmp($this->classes[$class]["functions"][$name]["type"],"VOID") + && $this->classes[$class]["return_value_set"]==0) + { + $compiler->SetElementError($this->classes[$class]["functions"][$name]["do"]["file"],$this->classes[$class]["functions"][$name]["do"]["path"],"it was not set the class function return value"); + return(0); + } + $this->classes[$class]["function_name"]=$function_name; + $this->classes[$class]["return_type"]=$return_type; + $this->classes[$class]["return_value_set"]=$return_value_set; + } + return(1); + } + Function InheritedFunctionClass(&$class,$function) { for(;;$class=$this->classes[$class]["parent"]) @@ -565,7 +729,7 @@ class metal_class_class extends metal_ba Function Call(&$compiler,&$code,&$context,&$call,$function) { - $class=$subclass=(IsSet($call["subclass"]) ? $call["subclass"] : 0); + $class=$subclass=(IsSet($call["subclass"]) ? $call["subclass"] : $this->current_subclass); $elements=$code->structure[$context->path]["Elements"]; for($element=0;$element<$elements;$element++) { @@ -673,219 +837,6 @@ class metal_class_class extends metal_ba return(1); } - Function GenerateFunction(&$compiler,$class,$name) - { - if(!IsSet($this->classes[$class]["functions"][$name]["do"]["code"])) - { - $this->classes[$class]["functions"][$name]["do"]["code"]=array(); - $function_name=$this->classes[$class]["function_name"]; - $return_type=$this->classes[$class]["return_type"]; - $return_value_set=$this->classes[$class]["return_value_set"]; - $this->classes[$class]["function_name"]=$name; - $this->classes[$class]["return_type"]=$this->classes[$class]["functions"][$name]["type"]; - $this->classes[$class]["return_value_set"]=0; - $action_context=new metal_execution_context_class; - $action_context->file=$this->classes[$class]["functions"][$name]["do"]["file"]; - $action_context->path=$this->classes[$class]["functions"][$name]["do"]["path"]; - $action_context->result=array(); - $functions=array( - "instancevariable", - "instancecall", - "functionargument", - "return" - ); - if(!$compiler->AddContextFunctions(&$action_context,$this->object_name,&$functions,&$level)) - return(0); - if(!$compiler->GetOutputData($this->classes[$class]["functions"][$name]["do"]["file"],$this->classes[$class]["functions"][$name]["do"]["path"],&$this->classes[$class]["functions"][$name]["do"]["code"],"it were not defined valid class function do statements",1)) - return(0); - if(!$compiler->RemoveContextFunctions(&$action_context,$this->object_name,$level)) - return(0); - if(strcmp($this->classes[$class]["functions"][$name]["type"],"VOID") - && $this->classes[$class]["return_value_set"]==0) - { - $compiler->SetElementError($this->classes[$class]["functions"][$name]["do"]["file"],$this->classes[$class]["functions"][$name]["do"]["path"],"it was not set the class function return value"); - return(0); - } - $this->classes[$class]["function_name"]=$function_name; - $this->classes[$class]["return_type"]=$return_type; - $this->classes[$class]["return_value_set"]=$return_value_set; - } - return(1); - } - - Function GenerateClass(&$compiler,&$result,&$initialization_result,$class) - { - $result=array(); - $result[]=array( - "Data"=>0, - "Type"=>"RESETINDENT" - ); - if(strcmp($this->classes[$class]["file"],"")) - { - $result[]=array( - "Data"=>"if(!defined(\"".$this->classes[$class]["tag"]."\"))", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>"{", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>1, - "Type"=>"INDENT" - ); - $result[]=array( - "Data"=>"define(\"".$this->classes[$class]["tag"]."\",1);", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>1, - "Type"=>"OUTDENT" - ); - } - $result[]=array( - "Data"=>"", - "Type"=>"COMMAND" - ); - if(IsSet($this->classes[$class]["comment"])) - { - $result[]=array( - "Data"=>"/*", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>" *", - "Type"=>"COMMAND" - ); - for($line=$this->classes[$class]["comment"];strcmp($line,"");) - { - $line=strtok($line,"\r\n"); - $result[]=array( - "Data"=>" * $line", - "Type"=>"COMMAND" - ); - $line=strtok(""); - } - $result[]=array( - "Data"=>" *", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>" */", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>"", - "Type"=>"COMMAND" - ); - } - $result[]=array( - "Data"=>"class ".$this->classes[$class]["name"].(IsSet($this->classes[$class]["parent"]) ? " extends ".$this->classes[$this->classes[$class]["parent"]]["name"] : ""), - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>"{", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>1, - "Type"=>"INDENT" - ); - for(Reset($this->classes[$class]["variables"]),$function=0;$functionclasses[$class]["variables"]);$function++,Next($this->classes[$class]["variables"])) - { - $name=Key($this->classes[$class]["variables"]); - $value=(IsSet($this->classes[$class]["variables"][$name]["value"]) ? "=".$this->classes[$class]["variables"][$name]["value"] : ""); - $result[]=array( - "Data"=>"var \$$name$value;", - "Type"=>"COMMAND" - ); - } - for(Reset($this->classes[$class]["functions"]),$function=0;$functionclasses[$class]["functions"]);$function++,Next($this->classes[$class]["functions"])) - { - $name=Key($this->classes[$class]["functions"]); - if(!$this->GenerateFunction(&$compiler,$class,$name)) - return(0); - if($function>0 - || count($this->classes[$class]["variables"])) - { - $result[]=array( - "Data"=>1, - "Type"=>"OUTDENT" - ); - $result[]=array( - "Data"=>"", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>1, - "Type"=>"INDENT" - ); - } - $argument_list=""; - if(IsSet($this->classes[$class]["functions"][$name]["Arguments"])) - { - $arguments=$this->classes[$class]["functions"][$name]["Arguments"]; - for(Reset($arguments),$argument=0;$argument0) - $argument_list.=","; - $argument_list.=(IsSet($arguments[Key($arguments)]["reference"]) ? "&" : "")."\$".Key($arguments); - } - } - $result[]=array( - "Data"=>"Function $name($argument_list)", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>"{", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>1, - "Type"=>"INDENT" - ); - for($part=0;$partclasses[$class]["functions"][$name]["do"]["code"]);$part++) - { - if(strcmp($this->classes[$class]["functions"][$name]["do"]["code"][$part]["Type"],"INITIALIZATION")) - $result[]=$this->classes[$class]["functions"][$name]["do"]["code"][$part]; - else - $initialization_result[]=$this->classes[$class]["functions"][$name]["do"]["code"][$part]; - } - $result[]=array( - "Data"=>1, - "Type"=>"OUTDENT" - ); - $result[]=array( - "Data"=>"}", - "Type"=>"COMMAND" - ); - } - $result[]=array( - "Data"=>1, - "Type"=>"OUTDENT" - ); - $result[]=array( - "Data"=>"};", - "Type"=>"COMMAND" - ); - $result[]=array( - "Data"=>"", - "Type"=>"COMMAND" - ); - if(strcmp($this->classes[$class]["file"],"")) - { - $result[]=array( - "Data"=>"}", - "Type"=>"COMMAND" - ); - } - $result[]=array( - "Data"=>0, - "Type"=>"RESTOREINDENT" - ); - return(1); - } - Function GetSubclassArgument(&$compiler,$file,$path,&$values) { if(IsSet($value["subclass"])) @@ -926,7 +877,7 @@ class metal_class_class extends metal_ba $compiler->SetElementError($arguments->file,$element_path,$data["Tag"]." is not a supported class object scope tag"); return(0); } - if($tags[$data["Tag"]]) + if(IsSet($tags[$data["Tag"]])) { $compiler->SetElementError($arguments->file,$element_path,"it was specified the class scope tag ".$data["Tag"]." more than once"); return(0); @@ -942,28 +893,92 @@ class metal_class_class extends metal_ba return(0); } } - $class=(IsSet($output["subclass"]) ? $output["subclass"] : 0); + $class=(IsSet($output["subclass"]) ? $output["subclass"] : $this->current_subclass); return(1); } - Function Execute(&$compiler,&$code,$function,&$context,&$arguments_code,&$arguments) + Function IterateVariables(&$compiler,&$context,$class,&$variables,$protected,$public,$inherited) { - if(strcmp($compiler->language["name"],"PHP")) + for($class_variable=0,Reset($this->classes[$class]["variables"]);$class_variableclasses[$class]["variables"]);Next($this->classes[$class]["variables"]),$class_variable++) { - $compiler->SetElementError($context->file,$context->path,$compiler->language["name"]." is not a language supported by the class class"); - return(0); + $this->current_class=$class; + $this->current_variable=Key($this->classes[$class]["variables"]); + if(!IsSet($variables[$this->current_variable]) + && (($public + && !IsSet($this->classes[$class]["variables"][$this->current_variable]["protected"])) + || ($protected + && IsSet($this->classes[$class]["variables"][$this->current_variable]["protected"])))) + { + if(!$compiler->GetOutputData($context->file,$context->path,&$context->result,"it was not defined valid action for the class variables",1)) + return(0); + $variables[$this->current_variable]=$class; + } } - switch($function) + if($inherited + && IsSet($this->classes[$class]["parent"])) + return($this->IterateVariables($compiler,$context,$this->classes[$class]["parent"],&$variables,$protected,$public,$inherited)); + return(1); + } + + Function IterateFunctions(&$compiler,&$context,$class,&$functions,$protected,$public,$inherited) + { + for($class_function=0,Reset($this->classes[$class]["functions"]);$class_functionclasses[$class]["functions"]);Next($this->classes[$class]["functions"]),$class_function++) { - case "load": - $load=array(); - $elements=$arguments_code->structure[$arguments->path]["Elements"]; - for($element=0;$element<$elements;$element++) - { - $element_path=$arguments->path.",$element"; - $data=$arguments_code->structure[$element_path]; - if(GetType($data)=="array") - { + $this->current_class=$class; + $this->current_function=Key($this->classes[$class]["functions"]); + if(!IsSet($functions[$this->current_function]) + && (($public + && !IsSet($this->classes[$class]["functions"][$this->current_function]["protected"])) + || ($protected + && IsSet($this->classes[$class]["functions"][$this->current_function]["protected"])))) + { + if(!$compiler->GetOutputData($context->file,$context->path,&$context->result,"it was not defined valid action for the class functions",1)) + return(0); + $functions[$this->current_function]=$class; + } + } + if($inherited + && IsSet($this->classes[$class]["parent"])) + return($this->IterateFunctions($compiler,$context,$this->classes[$class]["parent"],&$functions,$protected,$public,$inherited)); + return(1); + } + + Function Execute(&$compiler,&$code,$function,&$context,&$arguments_code,&$arguments) + { + switch($compiler->language["name"]) + { + case "Java": + switch($function) + { + case "output": + case "functionargument": + case "return": + case "instancevariable": + case "instancecall": + case "call": + break; + default: + $compiler->SetElementError($context->file,$context->path,"$function function of the class class is not implemented for the language ".$compiler->language["name"]); + return(0); + } + break; + case "PHP": + break; + default: + $compiler->SetElementError($context->file,$context->path,$compiler->language["name"]." is not a language supported by the class class"); + return(0); + } + switch($function) + { + case "load": + $load=array(); + $elements=$arguments_code->structure[$arguments->path]["Elements"]; + for($element=0;$element<$elements;$element++) + { + $element_path=$arguments->path.",$element"; + $data=$arguments_code->structure[$element_path]; + if(GetType($data)=="array") + { switch($data["Tag"]) { case "subclass": @@ -995,6 +1010,11 @@ class metal_class_class extends metal_ba } } $subclass=(IsSet($load["subclass"]) ? $load["subclass"] : 0); + if(IsSet($this->classes[$subclass]["abstract"])) + { + $compiler->SetElementError($context->file,$context->path,"an abstract class can not be loaded"); + return(0); + } $relative_path=$compiler->RelativePath($this->classes[$subclass]["basepath"],$this->classes[$subclass]["file"]); $context->result[]=array( "Data"=>array( @@ -1104,6 +1124,11 @@ class metal_class_class extends metal_ba } } $subclass=(IsSet($new["subclass"]) ? $new["subclass"] : 0); + if(IsSet($this->classes[$subclass]["abstract"])) + { + $compiler->SetElementError($context->file,$context->path,"an abstract class can not be instanciated"); + return(0); + } $context->result[]=array( "Data"=>array( "Object"=>$this->object_name, @@ -1135,62 +1160,95 @@ class metal_class_class extends metal_ba break; case "instancecall": case "call": - $call=array(); - if(!$this->Call(&$compiler,&$arguments_code,&$arguments,&$call,$function) - || !$this->Call(&$compiler,&$code,&$context,&$call,$function)) + $message=array(); + if(!$this->Call(&$compiler,&$arguments_code,&$arguments,&$message,$function) + || !$this->Call(&$compiler,&$code,&$context,&$message,$function)) return(0); if((strcmp($function,"instancecall") - && !IsSet($call[$argument="object"])) - || !IsSet($call[$argument="function"])) + && !IsSet($message[$argument="object"])) + || !IsSet($message[$argument="function"])) { $compiler->SetElementError($context->file,$context->path,"it was not defined the class $function $argument argument"); return(0); } - $argument_list=""; - $class=$subclass=(IsSet($call["subclass"]) ? $call["subclass"] : 0); - $this->InheritedFunctionClass(&$class,$call["function"]); - if(IsSet($this->classes[$class]["functions"][$call["function"]]["Arguments"])) + $message["class"]=$subclass=(IsSet($message["subclass"]) ? $message["subclass"] : $this->current_subclass); + if(IsSet($this->classes[$subclass]["abstract"]) + && !strcmp($function,"call")) + { + $compiler->SetElementError($context->file,$context->path,"an abstract class can not be called"); + return(0); + } + $this->InheritedFunctionClass(&$message["class"],$message["function"]); + $message["argumentlist"]=array(); + if(IsSet($this->classes[$message["class"]]["functions"][$message["function"]]["Arguments"])) { - $arguments=$this->classes[$class]["functions"][$call["function"]]["Arguments"]; + $arguments=$this->classes[$message["class"]]["functions"][$message["function"]]["Arguments"]; for(Reset($arguments),$argument=0;$argumentSetElementError($context->file,$context->path,"it was not specified the class $function ".Key($arguments)." argument"); - return(0); + $argument_context=$message["arguments"][$argument_name]; + $evaluate_context=$context; + $evaluate_context->file=$argument_context["file"]; + $evaluate_context->path=$argument_context["path"]; + switch($this->classes[$message["class"]]["functions"][$message["function"]]["Arguments"][$argument_name]["parameter"]) + { + case "in": + $side="NOTLEFT"; + $error="it was not specified a valid class function $function argument ".$argument_context["type"]." input expression"; + break; + case "out": + $side="NOTRIGHT"; + $error="it was not specified a valid class function $function argument ".$argument_context["type"]." output expression"; + break; + case "inout": + $side="BOTH"; + $error="it was not specified a valid class function $function argument ".$argument_context["type"]." input/output expression"; + break; + } + if(!$compiler->GetValidExpression(&$evaluate_context,"ANY",$side,$error,0) + || !$compiler->GetExpressionValue(&$context,&$evaluate_context->result,&$argument_value,&$expression_type)) + return(0); + if($expression_type=="UNDEFINED" + && $side=="NOTRIGHT") + { + $variable=array( + "DeclarationFile"=>$evaluate_context->file, + "DeclarationPath"=>$evaluate_context->path.",0" + ); + if(!$compiler->QueryVariable(&$context,&$variable)) + return(0); + if($variable["Declared"]) + { + $variable["Type"]=$argument_context["type"]; + if(!$compiler->DeclareVariable(&$context,&$variable)) + return(0); + if(!$compiler->GetValidExpression(&$evaluate_context,$argument_context["type"],$side,$error,0) + || !$compiler->GetExpressionValue(&$context,&$evaluate_context->result,&$argument_value,&$expression_type)) + return(0); + } + } + if($expression_type!=$argument_context["type"]) + { + $compiler->SetElementError($evaluate_context->file,$evaluate_context->path,"it was specified an expression of type \"$expression_type\" where it was expected a ".$argument_context["type"]." expression for class $function ".$argument_name." argument"); + return(0); + } } - $argument_context=$call["arguments"][Key($arguments)]; - $evaluate_context=$context; - $evaluate_context->file=$argument_context["file"]; - $evaluate_context->path=$argument_context["path"]; - $reference=IsSet($argument_context["reference"]); - if(!$compiler->GetValidExpression(&$evaluate_context,$argument_context["type"],$reference ? "BOTH" : "NOTLEFT","it was not specified a valid class function $function argument ".$argument_context["type"]." ".($reference ? "reference" : "value")." expression",0) - || !$compiler->GetExpressionValue(&$context,&$evaluate_context->result,&$argument_value,&$expression_type)) - return(0); - if($argument>0) - $argument_list.=","; - $argument_list.=$argument_value; + else + { + if(!IsSet($arguments[$argument_name]["defaultvalue"])) + { + $compiler->SetElementError($context->file,$context->path,"it was not specified the class $function ".$argument_name." argument"); + return(0); + } + $argument_value=$arguments[$argument_name]["converteddefaultvalue"]; + } + $message["argumentlist"][]=$argument_value; } } - $statement=(strcmp($function,"instancecall") ? $call["object"] : "\$this")."->".$call["function"]."($argument_list)"; - if(strcmp($this->classes[$class]["functions"][$call["function"]]["type"],"VOID")) - { - $context->result[]=array( - "Data"=>array( - "Value"=>$statement, - "Type"=>$this->classes[$class]["functions"][$call["function"]]["type"], - "Side"=>"RIGHT" - ), - "Type"=>"EXPRESSION" - ); - } - else - { - $context->result[]=array( - "Data"=>$statement.";", - "Type"=>"COMMAND" - ); - } + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,$function,&$message)) + return(0); break; case "return": if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) @@ -1209,36 +1267,31 @@ class metal_class_class extends metal_ba if(!$compiler->GetValidExpression(&$evaluate_context,$this->classes[$class]["return_type"],"NOTLEFT","it was not specified a valid class function return ".$this->classes[$class]["return_type"]." expression",1) || !$compiler->GetExpressionValue(&$context,&$evaluate_context->result,&$return_value,&$expression_type)) return(0); - $context->result[]=array( - "Data"=>"return $return_value;", - "Type"=>"COMMAND" + $message=array( + "value"=>$return_value ); + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,"return",&$message)) + return(0); $this->classes[$class]["return_value_set"]=1; break; case "instancevariable": - if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) + $message=array(); + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$message["class"],0,$tags)) return(0); - if(!strcmp($this->classes[$class]["return_type"],"")) + if(!strcmp($this->classes[$message["class"]]["return_type"],"")) { $compiler->SetElementError($context->file,$context->path,"the instance variable is being accessed from outside a class function"); return(0); } - if(!$compiler->GetValidName($context->file,$context->path,&$name,"it was not specified a valid class variable name")) + if(!$compiler->GetValidName($context->file,$context->path,&$message["name"],"it was not specified a valid class variable name")) return(0); - - if(!$this->InheritedVariableClass(&$class,$name)) + if(!$this->InheritedVariableClass(&$message["class"],$message["name"])) { - $compiler->SetElementError($context->file,$context->path,"it was not specified a defined class variable name (\"$name\")"); + $compiler->SetElementError($context->file,$context->path,"it was not specified a defined class variable name (\"".$message["name"]."\")"); return(0); } - $context->result[]=array( - "Data"=>array( - "Value"=>"\$"."this->$name", - "Type"=>$this->classes[$class]["variables"][$name]["type"], - "Side"=>"BOTH" - ), - "Type"=>"EXPRESSION" - ); + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,"instancevariable",&$message)) + return(0); break; case "objectvariable": $object_variable=array(); @@ -1286,11 +1339,21 @@ class metal_class_class extends metal_ba if(!$compiler->GetValidName($context->file,$context->path,&$name,"it was not specified a valid class variable name")) return(0); $subclass=(IsSet($object_variable["subclass"]) ? $object_variable["subclass"] : 0); + if(IsSet($this->classes[$subclass]["abstract"])) + { + $compiler->SetElementError($context->file,$context->path,"abstract class variables can not be accessed"); + return(0); + } if(!$this->InheritedVariableClass(&$subclass,$name)) { $compiler->SetElementError($context->file,$context->path,"it was not specified a defined class variable name (\"$name\")"); return(0); } + if(IsSet($this->classes[$subclass]["variables"][$name]["protected"])) + { + $compiler->SetElementError($context->file,$context->path,"it was attempted to access an object protected variable (\"$name\") from outside the class scope"); + return(0); + } $context->result[]=array( "Data"=>array( "Value"=>$object_variable["object"]."->$name", @@ -1301,40 +1364,44 @@ class metal_class_class extends metal_ba ); break; case "functionargument": - if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) + $message=array(); + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$message["class"],0,$tags)) return(0); - if(!strcmp($this->classes[$class]["function_name"],"")) + if(!strcmp($this->classes[$message["class"]]["function_name"],"")) { $compiler->SetElementError($context->file,$context->path,"the function argument function is being from called outside a class function"); return(0); } - if(!$compiler->GetValidName($context->file,$context->path,&$name,"it was not specified a valid class function argument name")) + if(!$compiler->GetValidName($context->file,$context->path,&$message["name"],"it was not specified a valid class function argument name")) return(0); - if(!IsSet($this->classes[$class]["functions"][$this->classes[$class]["function_name"]]["Arguments"][$name])) + if(!IsSet($this->classes[$message["class"]]["functions"][$this->classes[$message["class"]]["function_name"]]["Arguments"][$message["name"]])) { - $compiler->SetElementError($context->file,$context->path,"it was specified an unknown class function argument (\"$name\")"); + $compiler->SetElementError($context->file,$context->path,"it was specified an unknown class function argument (\"".$message["name"]."\")"); return(0); } - $argument=$this->classes[$class]["functions"][$this->classes[$class]["function_name"]]["Arguments"][$name]; - $context->result[]=array( - "Data"=>array( - "Value"=>"\$".$name, - "Type"=>$argument["type"], - "Side"=>"BOTH" - ), - "Type"=>"EXPRESSION" - ); + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,"functionargument",&$message)) + return(0); break; case "output": if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) return(0); + if(IsSet($this->classes[$class]["abstract"])) + { + $compiler->SetElementError($context->file,$context->path,"abstract classes can not be generated"); + return(0); + } if(!strcmp($this->classes[$class]["file"],"")) { $compiler->SetElementError($context->file,$context->path,"it was not specified the class output file"); return(0); } - if(!$this->GenerateClass(&$compiler,&$result,&$initialization_result,$class) - || !$compiler->GenerateOutput(&$context,&$result,&$output,"",0) + $message=array( + "class"=>$class, + "result"=>array(), + "initialization"=>array() + ); + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,"output",&$message) + || !$compiler->GenerateOutput(&$context,&$message["result"],&$output,"",0) || !$compiler->CreateContextOutputDirectory(dirname($this->classes[$class]["file"]),&$context,"it was not possible to create the directory for the class output file \"".dirname($this->classes[$class]["file"])."\"")) return(0); if(!($output_file=@fopen($this->classes[$class]["file"],"w"))) @@ -1363,6 +1430,7 @@ class metal_class_class extends metal_ba return(0); break; case "getproperty": + case "definedproperty": if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) return(0); if(!$compiler->GetValidName($context->file,$context->path,&$property,"it was not specified a valid class property name")) @@ -1372,17 +1440,40 @@ class metal_class_class extends metal_ba case "file": case "basepath": case "tag": - case "comment": + case "version": + case "copyright": case "title": case "author": case "authoraddress": - if(!IsSet($this->classes[$class][$property])) + if(!strcmp($function,"getproperty")) { - $compiler->SetElementError($context->file,$context->path,"it was requested a property value (\"$property\") not defined for the specified class"); - return(0); + if(!IsSet($this->classes[$class][$property])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested a property value (\"$property\") not defined for the specified class"); + return(0); + } + $context->result[]=array( + "Data"=>$this->classes[$class][$property], + "Type"=>"DATA" + ); + } + else + { + $context->result[]=array( + "Data"=>(IsSet($this->classes[$class][$property]) ? "1" : "0"), + "Type"=>"DATA" + ); } + break; + case "subclass": + $context->result[]=array( + "Data"=>(!strcmp($function,"getproperty") ? (IsSet($this->classes[$class]["parent"]) ? "1" : "0") : "1"), + "Type"=>"DATA" + ); + break; + case "abstract": $context->result[]=array( - "Data"=>$this->classes[$class][$property], + "Data"=>(!strcmp($function,"getproperty") ? (IsSet($this->classes[$class]["abstract"]) ? "1" : "0") : "1"), "Type"=>"DATA" ); break; @@ -1391,37 +1482,285 @@ class metal_class_class extends metal_ba return(0); } break; + case "definetypes": + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,0,$tags)) + return(0); + $elements=$code->structure[$context->path]["Elements"]; + for($element=0;$element<$elements;$element++) + { + $element_path=$context->path.",$element"; + $data=$code->structure[$element_path]; + if(GetType($data)=="array") + { + switch($data["Tag"]) + { + case "VOID": + case "STRING": + case "INTEGER": + case "FLOAT": + case "BOOLEAN": + case "OBJECT": + case "ARRAY": + case "HASH": + if(IsSet($this->classes[$class]["types"][$data["Tag"]])) + { + $compiler->SetElementError($context->file,$element_path,"it was defined the class data type \"".$data["Tag"]."\" more than once"); + return(0); + } + if(!$compiler->GetValidData($context->file,$element_path,&$type,"it was not specified a valid class data type option")) + return(0); + $type_name=$data["Tag"]; + $this->classes[$class]["types"][$type_name]=$type; + $parent=$class; + while(IsSet($this->classes[$parent]["parent"])) + { + $parent=$this->classes[$parent]["parent"]; + $this->classes[$parent]["types"][$type_name]=$type; + } + break; + default: + $compiler->SetElementError($context->file,$element_path,"it was not defined a valid class data type"); + return(0); + } + } + else + { + if(!$compiler->CheckWhiteSpace($context->file,$data,$element_path)) + return(0); + } + } + break; case "forallfunctions": if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,1,$tags)) return(0); if(IsSet($tags["idiom"]) && !$compiler->GetValidName($tags["idiom"]->file,$tags["idiom"]->path,&$idiom,"it was not specified a valid class documentation idiom tag")) return(0); + $protected=$public=1; + $inherited=0; + if(IsSet($tags["protected"])) + { + if(!$compiler->GetValidData($tags["protected"]->file,$tags["protected"]->path,&$value,"it was not specified a valid class function public value")) + return(0); + switch($value) + { + case "1": + case "": + $protected=1; + break; + case "0": + $protected=0; + break; + default: + $compiler->SetElementError($tags["protected"]->file,$tags["protected"]->path,"it was not specified a valid class function protected value"); + return(0); + } + } + if(IsSet($tags["public"])) + { + if(!$compiler->GetValidData($tags["public"]->file,$tags["public"]->path,&$value,"it was not specified a valid class function public value")) + return(0); + switch($value) + { + case "1": + case "": + $public=1; + break; + case "0": + $public=0; + break; + default: + $compiler->SetElementError($tags["public"]->file,$tags["public"]->path,"it was not specified a valid class function public value"); + return(0); + } + } + if(IsSet($tags["inherited"])) + { + if(!$compiler->GetValidData($tags["inherited"]->file,$tags["inherited"]->path,&$value,"it was not specified a valid class function inherited value")) + return(0); + switch($value) + { + case "1": + case "": + $inherited=1; + break; + case "0": + $inherited=0; + break; + default: + $compiler->SetElementError($tags["inherited"]->file,$tags["inherited"]->path,"it was not specified a valid class function inherited value"); + return(0); + } + } $functions=array( "functionname", - "functiontype" + "functiontype", + "functiontypename", + "functionistype", + "functionhasarguments", + "forallarguments" + ); + if(!$compiler->AddContextFunctions(&$context,$this->object_name,&$functions,&$level)) + return(0); + $current_class=$this->current_class; + $current_function=$this->current_function; + $functions=array(); + $success=$this->IterateFunctions($compiler,$context,$class,$functions,$protected,$public,$inherited); + $this->current_class=$current_class; + $this->current_function=$current_function; + if(!$compiler->RemoveContextFunctions(&$context,$this->object_name,$level) + || !$success) + return(0); + break; + case "forallvariables": + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,1,$tags)) + return(0); + if(IsSet($tags["idiom"]) + && !$compiler->GetValidName($tags["idiom"]->file,$tags["idiom"]->path,&$idiom,"it was not specified a valid class documentation idiom tag")) + return(0); + $protected=$public=1; + $inherited=0; + if(IsSet($tags["protected"])) + { + if(!$compiler->GetValidData($tags["protected"]->file,$tags["protected"]->path,&$value,"it was not specified a valid class variable public value")) + return(0); + switch($value) + { + case "1": + case "": + $protected=1; + break; + case "0": + $protected=0; + break; + default: + $compiler->SetElementError($tags["protected"]->file,$tags["protected"]->path,"it was not specified a valid class variable protected value"); + return(0); + } + } + if(IsSet($tags["public"])) + { + if(!$compiler->GetValidData($tags["public"]->file,$tags["public"]->path,&$value,"it was not specified a valid class variable public value")) + return(0); + switch($value) + { + case "1": + case "": + $public=1; + break; + case "0": + $public=0; + break; + default: + $compiler->SetElementError($tags["public"]->file,$tags["public"]->path,"it was not specified a valid class variable public value"); + return(0); + } + } + if(IsSet($tags["inherited"])) + { + if(!$compiler->GetValidData($tags["inherited"]->file,$tags["inherited"]->path,&$value,"it was not specified a valid class variable inherited value")) + return(0); + switch($value) + { + case "1": + case "": + $inherited=1; + break; + case "0": + $inherited=0; + break; + default: + $compiler->SetElementError($tags["inherited"]->file,$tags["inherited"]->path,"it was not specified a valid class variable inherited value"); + return(0); + } + } + $functions=array( + "variablename", + "variabletype", + "variabletypename", + "definedvariabledefaultvalue", + "variabledefaultvalue", + "variableconvertedvalue" ); if(!$compiler->AddContextFunctions(&$context,$this->object_name,&$functions,&$level)) return(0); $current_class=$this->current_class; + $current_variable=$this->current_variable; + $variables=array(); + $success=$this->IterateVariables($compiler,$context,$class,$variables,$protected,$public,$inherited); + $this->current_class=$current_class; + $this->current_variable=$current_variable; + if(!$compiler->RemoveContextFunctions(&$context,$this->object_name,$level) + || !$success) + return(0); + break; + case "forallarguments": + if(!strcmp($this->current_function,"")) + { + $compiler->SetElementError($context->file,$context->path,"it was requested to iterate over function arguments outside a function definition scope"); + return(0); + } + if(IsSet($tags["idiom"]) + && !$compiler->GetValidName($tags["idiom"]->file,$tags["idiom"]->path,&$idiom,"it was not specified a valid class documentation idiom tag")) + return(0); + $current_class=$this->current_class; $current_function=$this->current_function; - for($class_function=0,Reset($this->classes[$class]["functions"]);$class_functionclasses[$class]["functions"]);Next($this->classes[$class]["functions"]),$class_function++) + $current_argument=$this->current_argument; + if(!IsSet($this->classes[$current_class]["functions"][$current_function]["Arguments"])) + break; + $functions=array( + "argumentname", + "argumenttype", + "argumenttypename", + "argumentparameter", + "lastargument" + ); + if(!$compiler->AddContextFunctions(&$context,$this->object_name,&$functions,&$level)) + return(0); + for($this->current_argument_number=0,Reset($this->classes[$current_class]["functions"][$current_function]["Arguments"]);$this->current_argument_numberclasses[$current_class]["functions"][$current_function]["Arguments"]);Next($this->classes[$current_class]["functions"][$current_function]["Arguments"]),$this->current_argument_number++) { - $this->current_class=$class; - $this->current_function=Key($this->classes[$class]["functions"]); - if(!$compiler->GetOutputData($context->file,$context->path,&$context->result,"it was not defined valid action for the class functions",1)) + $this->current_class=$current_class; + $this->current_function=$current_function; + $this->current_argument=Key($this->classes[$current_class]["functions"][$current_function]["Arguments"]); + if(!$compiler->GetOutputData($context->file,$context->path,&$context->result,"it was not defined valid action for the class function arguments",0)) { $this->current_class=$current_class; $this->current_function=$current_function; + $this->current_argument=$current_argument; return(0); } } $this->current_class=$current_class; $this->current_function=$current_function; + $this->current_argument=$current_argument; if(!$compiler->RemoveContextFunctions(&$context,$this->object_name,$level)) return(0); break; + case "forallparentclasses": + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,1,$tags)) + return(0); + if(IsSet($tags["idiom"]) + && !$compiler->GetValidName($tags["idiom"]->file,$tags["idiom"]->path,&$idiom,"it was not specified a valid class documentation idiom tag")) + return(0); + $functions=array(); + if(!$compiler->AddContextFunctions(&$context,$this->object_name,&$functions,&$level)) + return(0); + $current_class=$this->current_class; + $this->current_class=$class; + $success=1; + while(IsSet($this->classes[$this->current_class]["parent"])) + { + $this->current_class=$this->classes[$this->current_class]["parent"]; + if(!($success=$compiler->GetOutputData($context->file,$context->path,&$context->result,"it was not defined valid action for the class parentclasses",0))) + break; + } + $this->current_class=$current_class; + if(!$compiler->RemoveContextFunctions(&$context,$this->object_name,$level) + || !$success) + return(0); + break; case "getdocumentation": + case "defineddocumentation": if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,1,$tags)) return(0); if(!IsSet($tags["idiom"])) @@ -1433,19 +1772,138 @@ class metal_class_class extends metal_ba return(0); if(!$compiler->GetValidName($context->file,$context->path,&$tag,"it was not specified a valid class documentation tag")) return(0); - if(!IsSet($this->classes[$class]["documentation"][$idiom][$tag])) + $inherited=0; + if(IsSet($tags["inherited"])) { - $compiler->SetElementError($context->file,$context->path,"it was requested the value of a documentation tag (\"$property\") that is not defined for the specified class"); - return(0); + if(!$compiler->GetValidData($tags["inherited"]->file,$tags["inherited"]->path,&$value,"it was not specified a valid class function inherited value")) + return(0); + switch($value) + { + case "1": + case "": + $inherited=1; + break; + case "0": + $inherited=0; + break; + default: + $compiler->SetElementError($tags["inherited"]->file,$tags["inherited"]->path,"it was not specified a valid class function inherited value"); + return(0); + } + } + if(strcmp($this->current_argument,"")) + { + if($inherited) + { + while(!IsSet($this->classes[$class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["documentation"][$idiom][$tag]) + && IsSet($this->classes[$class]["parent"])) + $class=$this->classes[$class]["parent"]; + } + if(strcmp($function,"defineddocumentation")) + { + if(!IsSet($this->classes[$class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["documentation"][$idiom][$tag])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the value of a documentation tag (\"$tag\") that is not defined for the specified class function argument"); + return(0); + } + if(!$compiler->GetOutputData($this->classes[$class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["documentation"][$idiom][$tag]->file,$this->classes[$class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["documentation"][$idiom][$tag]->path,&$context->result,"it was not defined valid class function argument documentation tag",0)) + return(0); + } + else + { + $context->result[]=array( + "Data"=>(IsSet($this->classes[$class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["documentation"][$idiom][$tag]) ? "1" : "0"), + "Type"=>"DATA" + ); + } + } + else + { + if(strcmp($this->current_function,"")) + { + if($inherited) + { + while(!IsSet($this->classes[$class]["functions"][$this->current_function]["documentation"][$idiom][$tag]) + && IsSet($this->classes[$class]["parent"])) + $class=$this->classes[$class]["parent"]; + } + if(strcmp($function,"defineddocumentation")) + { + if(!IsSet($this->classes[$class]["functions"][$this->current_function]["documentation"][$idiom][$tag])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the value of a documentation tag (\"$tag\") that is not defined for the specified class function"); + return(0); + } + if(!$compiler->GetOutputData($this->classes[$class]["functions"][$this->current_function]["documentation"][$idiom][$tag]->file,$this->classes[$class]["functions"][$this->current_function]["documentation"][$idiom][$tag]->path,&$context->result,"it was not defined valid class function argument documentation tag",0)) + return(0); + } + else + { + $context->result[]=array( + "Data"=>(IsSet($this->classes[$class]["functions"][$this->current_function]["documentation"][$idiom][$tag]) ? "1" : "0"), + "Type"=>"DATA" + ); + } + } + else + { + if(strcmp($this->current_variable,"")) + { + if($inherited) + { + while(!IsSet($this->classes[$class]["variables"][$this->current_variable]["documentation"][$idiom][$tag]) + && IsSet($this->classes[$class]["parent"])) + $class=$this->classes[$class]["parent"]; + } + if(strcmp($function,"defineddocumentation")) + { + if(!IsSet($this->classes[$class]["variables"][$this->current_variable]["documentation"][$idiom][$tag])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the value of a documentation tag (\"$tag\") that is not defined for the specified class variable"); + return(0); + } + if(!$compiler->GetOutputData($this->classes[$class]["variables"][$this->current_variable]["documentation"][$idiom][$tag]->file,$this->classes[$class]["variables"][$this->current_variable]["documentation"][$idiom][$tag]->path,&$context->result,"it was not defined valid class variable argument documentation tag",0)) + return(0); + } + else + { + $context->result[]=array( + "Data"=>(IsSet($this->classes[$class]["variables"][$this->current_variable]["documentation"][$idiom][$tag]) ? "1" : "0"), + "Type"=>"DATA" + ); + } + } + else + { + if(strcmp($function,"defineddocumentation")) + { + if(!IsSet($this->classes[$class]["documentation"][$idiom][$tag])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the value of a documentation tag (\"$tag\") that is not defined for the specified class"); + return(0); + } + if(!$compiler->GetOutputData($this->classes[$class]["documentation"][$idiom][$tag]->file,$this->classes[$class]["documentation"][$idiom][$tag]->path,&$context->result,"it was not defined valid class documentation tag",0)) + return(0); + } + else + { + $context->result[]=array( + "Data"=>(IsSet($this->classes[$class]["documentation"][$idiom][$tag]) ? "1" : "0"), + "Type"=>"DATA" + ); + } + } + } } - if(!$compiler->GetOutputData($this->classes[$class]["documentation"][$idiom][$tag]->file,$this->classes[$class]["documentation"][$idiom][$tag]->path,&$context->result,"it was not defined valid class documentation tag",0)) - return(0); break; case "functionname": case "functiontype": + case "functiontypename": + case "functionistype": + case "functionhasarguments": if(!strcmp($this->current_function,"")) { - $compiler->SetElementError($context->file,$context->path,"it was requested the name of function outside a function definition scope"); + $compiler->SetElementError($context->file,$context->path,"it was requested the $function of function outside a function definition scope"); return(0); } switch($function) @@ -1456,12 +1914,175 @@ class metal_class_class extends metal_ba case "functiontype": $value=$this->classes[$this->current_class]["functions"][$this->current_function]["type"]; break; + case "functiontypename": + $value=$this->classes[$this->current_class]["functions"][$this->current_function]["type"]; + if(IsSet($this->classes[$this->current_class]["types"][$value])) + $value=$this->classes[$this->current_class]["types"][$value]; + break; + case "functionistype": + if(!$compiler->GetValidData($context->file,$context->path,&$type,"it was not specified a valid class function return type")) + return(0); + switch($type) + { + case "VOID": + case "STRING": + case "INTEGER": + case "FLOAT": + case "BOOLEAN": + case "OBJECT": + case "ARRAY": + case "HASH": + break; + default: + $compiler->SetElementError($context->file,$context->path,"it was not defined a valid class function return type"); + return(0); + } + $value=(strcmp($type,$this->classes[$this->current_class]["functions"][$this->current_function]["type"]) ? "0" : "1"); + break; + case "functionhasarguments": + $value=(IsSet($this->classes[$this->current_class]["functions"][$this->current_function]["Arguments"]) ? "1" : "0"); + break; } $context->result[]=array( "Data"=>$value, "Type"=>"DATA" ); break; + case "argumentname": + case "argumenttype": + case "argumenttypename": + case "argumentparameter": + case "lastargument": + if(!strcmp($this->current_argument,"")) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the $function of function argument outside a function argument definition scope"); + return(0); + } + switch($function) + { + case "argumentname": + $value=$this->current_argument; + break; + case "argumenttype": + $value=$this->classes[$this->current_class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["type"]; + break; + case "argumenttypename": + $value=$this->classes[$this->current_class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["type"]; + if(IsSet($this->classes[$this->current_class]["types"][$value])) + $value=$this->classes[$this->current_class]["types"][$value]; + break; + case "argumentparameter": + $value=$this->classes[$this->current_class]["functions"][$this->current_function]["Arguments"][$this->current_argument]["parameter"]; + break; + case "lastargument": + $value=($this->current_argument_number+1==count($this->classes[$this->current_class]["functions"][$this->current_function]["Arguments"]) ? "1" : "0"); + break; + } + $context->result[]=array( + "Data"=>$value, + "Type"=>"DATA" + ); + break; + case "variablename": + case "variabletype": + case "variabletypename": + case "definedvariabledefaultvalue": + case "variabledefaultvalue": + case "variableconvertedvalue": + if(!strcmp($this->current_variable,"")) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the $function of variable outside a variable definition scope"); + return(0); + } + switch($function) + { + case "variablename": + $value=$this->current_variable; + break; + case "variabletype": + $value=$this->classes[$this->current_class]["variables"][$this->current_variable]["type"]; + break; + case "variabletypename": + $value=$this->classes[$this->current_class]["variables"][$this->current_variable]["type"]; + if(IsSet($this->classes[$this->current_class]["types"][$value])) + $value=$this->classes[$this->current_class]["types"][$value]; + break; + case "definedvariabledefaultvalue": + $value=(IsSet($this->classes[$this->current_class]["variables"][$this->current_variable]["value"]) ? "1" : "0"); + break; + case "variabledefaultvalue": + if(!IsSet($this->classes[$this->current_class]["variables"][$this->current_variable]["value"])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the value of a class variable (".$this->current_variable.") that does not have a defined default value"); + return(0); + } + $value=$this->classes[$this->current_class]["variables"][$this->current_variable]["value"]; + break; + case "variableconvertedvalue": + if(!IsSet($this->classes[$this->current_class]["variables"][$this->current_variable]["convertedvalue"])) + { + $compiler->SetElementError($context->file,$context->path,"it was requested the convertedvalue of a class variable (".$this->current_variable.") that does not have a defined default value"); + return(0); + } + $value=$this->classes[$this->current_class]["variables"][$this->current_variable]["convertedvalue"]; + break; + } + $context->result[]=array( + "Data"=>$value, + "Type"=>"DATA" + ); + break; + case "examplecode": + if(!$this->GetClassScope(&$compiler,&$arguments_code,&$arguments,&$class,1,$tags)) + return(0); + $result=array(); + if(!$compiler->GetOutputData($context->file,$context->path,&$result,"invalid example code",1)) + return(0); + $initialization=1; + if(IsSet($tags["initialization"])) + { + if(!$compiler->GetValidData($tags["initialization"]->file,$tags["initialization"]->path,&$value,"it was not specified a valid class example code initialization value")) + return(0); + switch($value) + { + case "1": + case "": + $initialization=1; + break; + case "0": + $initialization=0; + break; + default: + $compiler->SetElementError($tags["initialization"]->file,$tags["initialization"]->path,"it was not specified a valid class example code initialization value"); + return(0); + } + } + if($initialization) + { + if(!$compiler->GenerateOutput(&$context,&$result,&$output,"",0)) + return(0); + } + else + { + for($stripped=array(),$part=0;$partGenerateOutput(&$context,&$stripped,&$output,"",0)) + return(0); + } + $context->result[]=array( + "Data"=>$output, + "Type"=>"DATA" + ); + break; default: $compiler->SetElementError($context->file,$context->path,$function." is not a supported class object function"); return(0); @@ -1477,9 +2098,13 @@ class metal_class_class extends metal_ba return(0); } $class=$this->subclasses[$object_context]; - for($parent=$class;$parent!=0;) + if(IsSet($this->classes[$class]["abstract"])) + { + $compiler->SetElementError($context->file,$context->path,"abstract class functions arguments can not be accessed"); + return(0); + } + for($parent=$class;$parent!=0 && !IsSet($this->classes[$parent=$this->classes[$parent]["parent"]]["abstract"]);) { - $parent=$this->classes[$parent]["parent"]; $context->result[]=array( "Data"=>array( "Object"=>$this->object_name, @@ -1524,10 +2149,17 @@ class metal_class_class extends metal_ba } else { - if(!$this->GenerateClass(&$compiler,&$result,&$context->result,$class)) + $message=array( + "class"=>$class, + "result"=>array(), + "initialization"=>array() + ); + if(!$this->language_bindings->Execute(&$compiler,&$context,&$this,"output",&$message)) return(0); - for($part=0;$partresult[]=$result[$part]; + for($part=0;$partresult[]=$message["initialization"][$part]; + for($part=0;$partresult[]=$message["result"][$part]; } return(1); }