You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Expression.java 11 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. MIT License
  3. Copyright (c) 2018-2019 Gang ZHANG
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in all
  11. copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18. SOFTWARE.
  19. */
  20. package depends.entity;
  21. import depends.entity.repo.EntityRepo;
  22. import depends.relations.IBindingResolver;
  23. import java.io.Serializable;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. /**
  27. * Expression
  28. */
  29. public class Expression implements Serializable{
  30. private static final long serialVersionUID = 1L;
  31. public Integer id;
  32. private String text; // for debug purpose
  33. private GenericName rawType; // the raw type name
  34. private GenericName identifier; // the varName, or method name, etc.
  35. private boolean isSet = false; // is a set relation from right to leftHand
  36. private boolean isDot = false; // is a dot expression, will decuce variable tfype left to right
  37. private boolean isCall = false;
  38. private boolean isLogic = false;
  39. private boolean isCreate = false;
  40. private boolean isCast = false;
  41. private boolean isThrow = false;
  42. private boolean isStatement = false; //statement is only used for return type calcuation in some langs such as ruby
  43. //they will not be treat as real expressions in case of relation calculation
  44. private boolean deriveTypeFromChild = true;
  45. private Integer deduceTypeBasedId; //by default, parent expression type determined by most left child
  46. private Integer parentId = -1;
  47. private transient Expression parent;
  48. private transient List<VarEntity> deducedTypeVars = new ArrayList<>();
  49. private List<Integer> deducedTypeVarsId = new ArrayList<>();
  50. private transient List<FunctionEntity> deducedTypeFunctions= new ArrayList<>();
  51. private List<Integer> deducedTypeFunctionsId = new ArrayList<>();
  52. private Integer referredEntityId;
  53. private transient Entity referredEntity;
  54. private transient TypeEntity type; // the type we care - for relation calculation.
  55. private Location location = new Location();
  56. //for leaf, it equals to referredEntity.getType. otherwise, depends on child's type strategy
  57. /*
  58. * */
  59. public Expression() {
  60. deducedTypeVars = new ArrayList<>();
  61. deducedTypeFunctions = new ArrayList<>();
  62. }
  63. public Expression(Integer id) {
  64. this.id = id;
  65. deducedTypeVars = new ArrayList<>();
  66. deducedTypeFunctions = new ArrayList<>();
  67. }
  68. public void reload(EntityRepo repo, ArrayList<Expression> expressionList) {
  69. this.deducedTypeFunctions = new ArrayList<>();
  70. this.deducedTypeVars = new ArrayList<>();
  71. //recover parent relation
  72. if (parentId!=-1) {
  73. for (Expression expr:expressionList) {
  74. if (expr.id==parentId) {
  75. parent = expr;
  76. break;
  77. }
  78. }
  79. }
  80. //recover deducedTypeFunctionsId
  81. if (deducedTypeFunctionsId!=null) {
  82. for (Integer funcId:this.deducedTypeFunctionsId) {
  83. this.deducedTypeFunctions.add((FunctionEntity) repo.getEntity(funcId));
  84. }
  85. }
  86. //recover deducedTypeVars
  87. if (deducedTypeVarsId!=null) {
  88. for (Integer varId:this.deducedTypeVarsId) {
  89. this.deducedTypeVars.add((VarEntity) repo.getEntity(varId));
  90. }
  91. }
  92. //referer referredEntity -- TODO:maybe not require
  93. if (this.referredEntityId!=null && this.referredEntity==null) {
  94. this.referredEntity = repo.getEntity(this.referredEntityId);
  95. if (this.referredEntity ==null){
  96. System.err.println("unexpected: referred Entity is null" + this.referredEntityId + this.text+this.id);
  97. }
  98. }
  99. }
  100. /**
  101. * Set type of the expression
  102. * @param type
  103. * @param referredEntity
  104. * @param bindingResolver
  105. */
  106. public void setType(TypeEntity type, Entity referredEntity, IBindingResolver bindingResolver) {
  107. if (this.getReferredEntity()==null && referredEntity!=null) {
  108. this.setReferredEntity(referredEntity);
  109. }
  110. boolean changedType = false;
  111. if (this.type==null && type!=null) {
  112. this.type = type;
  113. for (VarEntity var:deducedTypeVars) {
  114. if (var!=null) {
  115. var.setType(this.type);
  116. }
  117. }
  118. for (FunctionEntity func:deducedTypeFunctions) {
  119. if (func!=null) {
  120. func.addReturnType(this.type);
  121. }
  122. }
  123. changedType = true;
  124. }
  125. if (this.referredEntity==null)
  126. this.setReferredEntity(this.type);
  127. if (changedType)
  128. deduceTheParentType(bindingResolver);
  129. }
  130. /**
  131. * deduce type of parent based on child's type
  132. * @param bindingResolver
  133. */
  134. private void deduceTheParentType(IBindingResolver bindingResolver) {
  135. if (this.type==null) return;
  136. if (this.parent==null) return;
  137. Expression parent = this.parent;
  138. if (parent.type != null)return;
  139. if (!parent.deriveTypeFromChild) return;
  140. //parent's type depends on first child's type
  141. if (parent.deduceTypeBasedId!=this.id) return;
  142. //if child is a built-in/external type, then parent must also a built-in/external type
  143. if (this.type.equals(TypeEntity.buildInType)) {
  144. parent.setType(TypeEntity.buildInType,TypeEntity.buildInType, bindingResolver);
  145. return;
  146. }
  147. /* if it is a logic expression, the return type/type is boolean. */
  148. if (parent.isLogic) {
  149. parent.setType(TypeEntity.buildInType,null, bindingResolver);
  150. }
  151. /* if it is a.b, and we already get a's type, b's type could be identified easily */
  152. else if (parent.isDot) {
  153. if (parent.isCall()) {
  154. List<Entity> funcs = this.getType().lookupFunctionInVisibleScope(parent.identifier);
  155. setReferredFunctions(bindingResolver, parent, funcs);
  156. }else {
  157. Entity var = this.getType().lookupVarInVisibleScope(parent.identifier);
  158. if (var!=null) {
  159. parent.setType(var.getType(),var, bindingResolver);
  160. parent.setReferredEntity(var);
  161. }else {
  162. List<Entity> funcs = this.getType().lookupFunctionInVisibleScope(parent.identifier);
  163. setReferredFunctions(bindingResolver,parent,funcs);
  164. }
  165. }
  166. if (parent.getType()==null) {
  167. parent.setType(bindingResolver.inferTypeFromName(this.getType(), parent.identifier),null, bindingResolver);
  168. }
  169. }
  170. /* if other situation, simple make the parent and child type same */
  171. else {
  172. parent.setType(type, null, bindingResolver);
  173. }
  174. if (parent.getReferredEntity()==null)
  175. parent.setReferredEntity(parent.type);
  176. }
  177. private void setReferredFunctions(IBindingResolver bindingResolver, Expression expr, List<Entity> funcs) {
  178. if (funcs ==null ||funcs.size()==0) return;
  179. Entity func = funcs.get(0);
  180. if (funcs.size()==1){
  181. expr.setType(func.getType(), func, bindingResolver);
  182. expr.setReferredEntity(func);
  183. return;
  184. }
  185. MultiDeclareEntities m = new MultiDeclareEntities(func, bindingResolver.getRepo().generateId());
  186. bindingResolver.getRepo().add(m);
  187. for (int i = 1; i< funcs.size(); i++) {
  188. m.add(funcs.get(i));
  189. }
  190. expr.setType(func.getType(), m, bindingResolver);
  191. expr.setReferredEntity(m);
  192. }
  193. private void setReferredEntity(Entity referredEntity) {
  194. this.referredEntity = referredEntity;
  195. if (this.referredEntity!=null) {
  196. this.referredEntityId = referredEntity.getId();
  197. }
  198. }
  199. public void addDeducedTypeVar(VarEntity var) {
  200. this.deducedTypeVars.add(var);
  201. this.deducedTypeVarsId.add(var.getId());
  202. }
  203. public void addDeducedTypeFunction(FunctionEntity function) {
  204. this.deducedTypeFunctions.add(function);
  205. this.deducedTypeFunctionsId.add(function.id);
  206. }
  207. public void setParent(Expression parent) {
  208. this.parent = parent;
  209. if (parent!=null)
  210. this.parentId = parent.id;
  211. if (parent!=null) {
  212. if (parent.deduceTypeBasedId==null)
  213. parent.deduceTypeBasedId = id;
  214. if (parent.isSet) {
  215. parent.deduceTypeBasedId = id;
  216. }
  217. }
  218. }
  219. public GenericName getIdentifier() {
  220. return this.identifier;
  221. }
  222. public GenericName getRawType() {
  223. return this.rawType;
  224. }
  225. public void setIdentifier(String name) {
  226. if (!validName(name)){
  227. return;
  228. }
  229. this.identifier = GenericName.build(name);
  230. }
  231. public void setIdentifier(GenericName name) {
  232. if (name==null) return;
  233. if (!validName(name.getName())){
  234. return;
  235. }
  236. this.identifier = name;
  237. }
  238. public void setRawType(GenericName name) {
  239. if (name==null) return;
  240. if (!validName(name.getName())){
  241. return;
  242. }
  243. this.rawType = name;
  244. }
  245. public void setRawType(String name) {
  246. if (name==null) return;
  247. if (!validName(name)){
  248. return;
  249. }
  250. this.rawType = GenericName.build(name);
  251. }
  252. public Expression getParent() {
  253. return this.parent;
  254. }
  255. public void setText(String text) {
  256. this.text = text;
  257. }
  258. public boolean isCall() {
  259. return isCall;
  260. }
  261. public boolean isSet() {
  262. return isSet;
  263. }
  264. public void setSet(boolean isSet) {
  265. this.isSet = isSet;
  266. }
  267. public boolean isDot() {
  268. return isDot;
  269. }
  270. public void setDot(boolean isDot) {
  271. this.isDot = isDot;
  272. }
  273. public boolean isLogic() {
  274. return isLogic;
  275. }
  276. public void setLogic(boolean isLogic) {
  277. this.isLogic = isLogic;
  278. }
  279. public boolean isCreate() {
  280. return isCreate;
  281. }
  282. public void setCreate(boolean isCreate) {
  283. this.isCreate = isCreate;
  284. }
  285. public boolean isCast() {
  286. return isCast;
  287. }
  288. public void setCast(boolean isCast) {
  289. this.isCast = isCast;
  290. }
  291. public boolean isThrow() {
  292. return isThrow;
  293. }
  294. public void setThrow(boolean isThrow) {
  295. this.isThrow = isThrow;
  296. }
  297. public boolean isStatement() {
  298. return isStatement;
  299. }
  300. public void setStatement(boolean isStatement) {
  301. this.isStatement = isStatement;
  302. }
  303. public void setCall(boolean isCall) {
  304. this.isCall = isCall;
  305. }
  306. public void disableDriveTypeFromChild() {
  307. deriveTypeFromChild = false ;
  308. }
  309. public Entity getReferredEntity() {
  310. return referredEntity;
  311. }
  312. public TypeEntity getType() {
  313. return type;
  314. }
  315. private boolean validName(String name) {
  316. if (name==null) return false;
  317. if (name.toLowerCase().equals("<literal>")) return true;
  318. if (name.toLowerCase().equals("<built-in>")) return true;
  319. return true;
  320. }
  321. @Override
  322. public String toString() {
  323. StringBuilder s = new StringBuilder();
  324. s.append("[").append(text).append("]").append("|")
  325. .append("rawType:").append(rawType).append("|")
  326. .append("identifier:").append(identifier).append("|")
  327. .append("prop:").append(isDot?"[dot]":"")
  328. .append(isSet?"[set]":"")
  329. .append(isLogic?"[bool]":"")
  330. .append(isCall?"[call]":"")
  331. .append(isCreate?"[new]":"")
  332. .append(isThrow?"[throw]":"").append("|")
  333. .append("parent:").append(parent==null?"nil":parent.text).append("|")
  334. .append("type:").append(type).append("|");
  335. return s.toString();
  336. }
  337. public void setLine(int lineNumber) {
  338. this.location.setLine(lineNumber);
  339. }
  340. public Location getLocation() {
  341. return location;
  342. }
  343. }

No Description

Contributors (2)