4 #include <stdlib.h> // For strtoll
7 // UNTIL IMPLEMENTED IN GRAMMAR
8 #define ACCESS_CLASSDATA(_class, baseClass) \
9 (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
11 #define YYLTYPE Location
15 extern int returnCode;
16 extern Expression parsedExpression;
18 public void SetYydebug(bool b) { yydebug = b; }
23 // TODO: Reset this to 0 on reinitialization
26 int expression_yyparse();
27 static Statement curCompound;
28 External curExternal, afterExternal;
29 static Type curSwitchType;
30 static Class currentClass;
32 public void SetThisClass(Class c) { thisClass = c; } public Class GetThisClass() { return thisClass; }
33 static char * thisNameSpace;
34 /*static */Class containerClass;
35 bool thisClassParams = true;
37 uint internalValueCounter;
40 Time findSymbolTotalTime;
43 // WARNING: PrintExpression CONCATENATES to string. Please initialize.
44 /*static */public void PrintExpression(Expression exp, char * string)
52 OutputExpression(exp, f);
54 count = strlen(string);
55 count += f.Read(string + count, 1, 1023);
61 int64 _strtoi64(char * string, char ** endString, int base)
67 for(c = 0; (ch = string[c]) && isspace(ch); c++);
69 else if(ch == '-') { sign = -1; c++; };
72 if(ch == 0 && string[c+1] == 'x')
85 for( ;(ch = string[c]); c++)
89 else if(ch >= '1' && ch <= '9')
91 else if(ch >= 'a' && ch <= 'z')
93 else if(ch >= 'A' && ch <= 'Z')
98 *endString = string + c;
110 *endString = string + c;
118 uint64 _strtoui64(char * string, char ** endString, int base)
124 for(c = 0; (ch = string[c]) && isspace(ch); c++);
126 else if(ch == '-') { sign = -1; c++; };
129 if(ch == 0 && string[c+1] == 'x')
142 for( ;(ch = string[c]); c++)
146 else if(ch >= '1' && ch <= '9')
148 else if(ch >= 'a' && ch <= 'z')
150 else if(ch >= 'A' && ch <= 'Z')
154 if(endString) *endString = string + c;
166 *endString = string + c;
174 Type ProcessTemplateParameterType(TemplateParameter param)
176 if(param && param.type == TemplateParameterType::type && (param.dataType || param.dataTypeString))
178 // TOFIX: Will need to free this Type
181 if(param.dataTypeString)
182 param.baseType = ProcessTypeString(param.dataTypeString, false);
184 param.baseType = ProcessType(param.dataType.specifiers, param.dataType.decl);
186 return param.baseType;
191 bool NeedCast(Type type1, Type type2)
193 if(!type1 || !type2 || type1.keepCast || type2.keepCast) return true;
195 if(type1.kind == templateType && type2.kind == int64Type && type2.passAsTemplate == false)
200 if(type1.kind == type2.kind)
209 if(type1.passAsTemplate && !type2.passAsTemplate)
211 return type1.isSigned != type2.isSigned;
213 return type1._class != type2._class;
215 return NeedCast(type1.type, type2.type);
217 return true; //false; ????
223 static void ReplaceClassMembers(Expression exp, Class _class)
225 if(exp.type == identifierExp && exp.identifier)
227 Identifier id = exp.identifier;
229 Symbol symbol = null;
230 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
232 // First, check if the identifier is declared inside the function
233 for(ctx = curContext; ctx != topContext.parent && !symbol; ctx = ctx.parent)
235 symbol = (Symbol)ctx.symbols.FindString(id.string);
240 // If it is not, check if it is a member of the _class
241 if(!symbol && ((!id._class || (id._class.name && !strcmp(id._class.name, "property"))) || (id.classSym && eClass_IsDerived(_class, id.classSym.registered))))
243 Property prop = eClass_FindProperty(_class, id.string, privateModule);
244 Method method = null;
245 DataMember member = null;
246 ClassProperty classProp = null;
249 method = eClass_FindMethod(_class, id.string, privateModule);
252 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
253 if(!prop && !method && !member)
255 classProp = eClass_FindClassProperty(_class, id.string);
257 if(prop || method || member || classProp)
259 // Replace by this.[member]
260 exp.type = memberExp;
261 exp.member.member = id;
262 exp.member.memberType = unresolvedMember;
263 exp.member.exp = QMkExpId("this");
264 //exp.member.exp.loc = exp.loc;
265 exp.addedThis = true;
267 else if(_class && _class.templateParams.first)
270 for(sClass = _class; sClass; sClass = sClass.base)
272 if(sClass.templateParams.first)
274 ClassTemplateParameter param;
275 for(param = sClass.templateParams.first; param; param = param.next)
277 if(param.type == expression && !strcmp(param.name, id.string))
279 Expression argExp = GetTemplateArgExpByName(param.name, _class, TemplateParameterType::expression);
284 OldList * specs = MkList();
286 FreeIdentifier(exp.member.member);
288 ProcessExpressionType(argExp);
290 decl = SpecDeclFromString(param.dataTypeString, specs, null);
292 exp.expType = ProcessType(specs, decl);
294 // *[expType] *[argExp]
295 exp.type = bracketsExp;
296 exp.list = MkListOne(MkExpOp(null, '*',
297 MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpOp(null, '&', argExp))));
308 ////////////////////////////////////////////////////////////////////////
309 // PRINTING ////////////////////////////////////////////////////////////
310 ////////////////////////////////////////////////////////////////////////
312 public char * PrintInt(int64 result)
315 if(result > MAXINT64)
316 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
318 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
319 return CopyString(temp);
322 public char * PrintUInt(uint64 result)
325 if(result > MAXDWORD)
326 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
327 else if(result > MAXINT)
328 sprintf(temp, FORMAT64HEX /*"0x%I64X"*/, result);
330 sprintf(temp, FORMAT64D /*"%I64d"*/, result);
331 return CopyString(temp);
334 public char * PrintInt64(int64 result)
337 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
338 return CopyString(temp);
341 public char * PrintUInt64(uint64 result)
344 if(result > MAXINT64)
345 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
347 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
348 return CopyString(temp);
351 public char * PrintHexUInt(uint64 result)
354 if(result > MAXDWORD)
355 sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
357 sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
358 return CopyString(temp);
361 public char * PrintHexUInt64(uint64 result)
364 if(result > MAXDWORD)
365 sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
367 sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
368 return CopyString(temp);
371 public char * PrintShort(short result)
374 sprintf(temp, "%d", (unsigned short)result);
375 return CopyString(temp);
378 public char * PrintUShort(unsigned short result)
382 sprintf(temp, "0x%X", (int)result);
384 sprintf(temp, "%d", result);
385 return CopyString(temp);
388 public char * PrintChar(char result)
391 if(result > 0 && isprint(result))
392 sprintf(temp, "'%c'", result);
394 sprintf(temp, "%d", result);
396 //sprintf(temp, "%#X", result);
397 sprintf(temp, "0x%X", (unsigned char)result);
398 return CopyString(temp);
401 public char * PrintUChar(unsigned char result)
404 sprintf(temp, "0x%X", result);
405 return CopyString(temp);
408 public char * PrintFloat(float result)
411 sprintf(temp, "%.16ff", result);
412 return CopyString(temp);
415 public char * PrintDouble(double result)
418 sprintf(temp, "%.16f", result);
419 return CopyString(temp);
422 ////////////////////////////////////////////////////////////////////////
423 ////////////////////////////////////////////////////////////////////////
425 //public Operand GetOperand(Expression exp);
427 #define GETVALUE(name, t) \
428 public bool Get##name(Expression exp, t * value2) \
430 Operand op2 = GetOperand(exp); \
431 if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
432 else if(op2.kind == intType) *value2 = (t) op2.ui; \
433 if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
434 else if(op2.kind == int64Type) *value2 = (t) op2.ui64; \
435 else if(op2.kind == intPtrType && op2.type.isSigned) *value2 = (t) op2.iptr; \
436 else if(op2.kind == intPtrType) *value2 = (t) op2.uiptr; \
437 else if(op2.kind == shortType && op2.type.isSigned) *value2 = (t) op2.s; \
438 else if(op2.kind == shortType) *value2 = (t) op2.us; \
439 else if(op2.kind == charType && op2.type.isSigned) *value2 = (t) op2.c; \
440 else if(op2.kind == charType) *value2 = (t) op2.uc; \
441 else if(op2.kind == floatType) *value2 = (t) op2.f; \
442 else if(op2.kind == doubleType) *value2 = (t) op2.d; \
443 else if(op2.kind == pointerType) *value2 = (t) op2.ui; \
450 GETVALUE(UInt, unsigned int);
451 GETVALUE(Int64, int64);
452 GETVALUE(UInt64, uint64);
453 GETVALUE(IntPtr, intptr);
454 GETVALUE(UIntPtr, uintptr);
455 GETVALUE(Short, short);
456 GETVALUE(UShort, unsigned short);
457 GETVALUE(Char, char);
458 GETVALUE(UChar, unsigned char);
459 GETVALUE(Float, float);
460 GETVALUE(Double, double);
462 void ComputeExpression(Expression exp);
464 void ComputeClassMembers(Class _class, bool isMember)
466 DataMember member = isMember ? (DataMember) _class : null;
467 Context context = isMember ? null : SetupTemplatesContext(_class);
468 if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) &&
469 (_class.type == bitClass || _class.structSize == _class.offset) && _class.computeSize))
472 int unionMemberOffset = 0;
475 if(!member && _class.destructionWatchOffset)
476 _class.memberOffset += sizeof(OldList);
478 // To avoid reentrancy...
479 //_class.structSize = -1;
482 DataMember dataMember;
483 for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
485 if(!dataMember.isProperty)
487 if(dataMember.type == normalMember && dataMember.dataTypeString && !dataMember.dataType)
489 /*if(dataMember.dataType)
491 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
492 /*if(!dataMember.dataType)
493 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
501 DataMember dataMember;
502 for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
504 if(!dataMember.isProperty && (dataMember.type != normalMember || dataMember.dataTypeString))
506 if(!isMember && _class.type == bitClass && dataMember.dataType)
508 BitMember bitMember = (BitMember) dataMember;
512 ComputeTypeSize(dataMember.dataType);
514 if(bitMember.pos == -1) bitMember.pos = _class.memberOffset;
515 if(!bitMember.size) bitMember.size = dataMember.dataType.size * 8;
517 _class.memberOffset = bitMember.pos + bitMember.size;
518 for(d = 0; d<bitMember.size; d++)
524 bitMember.mask = mask << bitMember.pos;
526 else if(dataMember.type == normalMember && dataMember.dataType)
531 // Prevent infinite recursion
532 if(dataMember.dataType.kind != classType ||
533 ((!dataMember.dataType._class || !dataMember.dataType._class.registered || dataMember.dataType._class.registered != _class ||
534 _class.type != structClass)))
535 ComputeTypeSize(dataMember.dataType);
537 if(dataMember.dataType.bitFieldCount)
539 bitFields += dataMember.dataType.bitFieldCount;
546 int size = (bitFields + 7) / 8;
550 // TESTING THIS PADDING CODE
553 member.structAlignment = Max(member.structAlignment, alignment);
555 if(member.memberOffset % alignment)
556 member.memberOffset += alignment - (member.memberOffset % alignment);
559 dataMember.offset = member.memberOffset;
560 if(member.type == unionMember)
561 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
564 member.memberOffset += size;
569 // TESTING THIS PADDING CODE
572 _class.structAlignment = Max(_class.structAlignment, alignment);
574 if(_class.memberOffset % alignment)
575 _class.memberOffset += alignment - (_class.memberOffset % alignment);
578 dataMember.offset = _class.memberOffset;
579 _class.memberOffset += size;
583 size = dataMember.dataType.size;
584 alignment = dataMember.dataType.alignment;
595 // TESTING THIS PADDING CODE
598 member.structAlignment = Max(member.structAlignment, alignment);
600 if(member.memberOffset % alignment)
601 member.memberOffset += alignment - (member.memberOffset % alignment);
604 dataMember.offset = member.memberOffset;
605 if(member.type == unionMember)
606 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
609 member.memberOffset += size;
614 // TESTING THIS PADDING CODE
617 _class.structAlignment = Max(_class.structAlignment, alignment);
619 if(_class.memberOffset % alignment)
620 _class.memberOffset += alignment - (_class.memberOffset % alignment);
623 dataMember.offset = _class.memberOffset;
624 _class.memberOffset += size;
629 ComputeClassMembers((Class)dataMember, true);
633 // THERE WASN'T A MAX HERE ? member.structAlignment = dataMember.structAlignment;
634 member.structAlignment = Max(member.structAlignment, dataMember.structAlignment);
635 dataMember.offset = member.memberOffset;
636 if(member.type == unionMember)
637 unionMemberOffset = Max(unionMemberOffset, dataMember.memberOffset);
639 member.memberOffset += dataMember.memberOffset;
643 _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
644 dataMember.offset = _class.memberOffset;
645 _class.memberOffset += dataMember.memberOffset;
653 int size = (bitFields + 7) / 8;
657 // TESTING THIS PADDING CODE
660 member.structAlignment = Max(member.structAlignment, alignment);
662 if(member.memberOffset % alignment)
663 member.memberOffset += alignment - (member.memberOffset % alignment);
666 if(member.type == unionMember)
667 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
670 member.memberOffset += size;
675 // TESTING THIS PADDING CODE
678 _class.structAlignment = Max(_class.structAlignment, alignment);
680 if(_class.memberOffset % alignment)
681 _class.memberOffset += alignment - (_class.memberOffset % alignment);
683 _class.memberOffset += size;
688 if(member && member.type == unionMember)
690 member.memberOffset = unionMemberOffset;
695 /*if(_class.type == structClass)
696 _class.size = _class.memberOffset;
700 if(_class.type != bitClass)
702 _class.structSize = (_class.base ? (_class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize) : 0) + _class.memberOffset;
706 for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
708 if(prop.isProperty && prop.isWatchable)
710 prop.watcherOffset = _class.structSize;
711 _class.structSize += sizeof(OldList);
719 for(derivative = _class.derivatives.first; derivative; derivative = derivative.next)
721 Class deriv = derivative.data;
723 if(deriv.computeSize)
725 // TESTING THIS NEW CODE HERE... TRYING TO FIX ScrollBar MEMBERS DEBUGGING
726 deriv.offset = /*_class.offset + */_class.structSize;
727 deriv.memberOffset = 0;
728 // ----------------------
730 deriv.structSize = deriv.offset;
732 ComputeClassMembers(deriv, false);
740 FinishTemplatesContext(context);
743 public void ComputeModuleClasses(Module module)
748 for(subModule = module.modules.first; subModule; subModule = subModule.next)
749 ComputeModuleClasses(subModule.data);
750 for(_class = module.classes.first; _class; _class = _class.next)
751 ComputeClassMembers(_class, false);
755 public int ComputeTypeSize(Type type)
757 uint size = type ? type.size : 0;
758 if(!size && type && !type.computing)
760 type.computing = true;
763 case charType: type.alignment = size = sizeof(char); break;
764 case intType: type.alignment = size = sizeof(int); break;
765 case int64Type: type.alignment = size = sizeof(int64); break;
766 case intPtrType: type.alignment = size = sizeof(intptr); break;
767 case longType: type.alignment = size = sizeof(long); break;
768 case shortType: type.alignment = size = sizeof(short); break;
769 case floatType: type.alignment = size = sizeof(float); break;
770 case doubleType: type.alignment = size = sizeof(double); break;
773 Class _class = type._class ? type._class.registered : null;
775 if(_class && _class.type == structClass)
777 // Ensure all members are properly registered
778 ComputeClassMembers(_class, false);
779 type.alignment = _class.structAlignment;
780 size = _class.structSize;
781 if(type.alignment && size % type.alignment)
782 size += type.alignment - (size % type.alignment);
785 else if(_class && (_class.type == unitClass ||
786 _class.type == enumClass ||
787 _class.type == bitClass))
790 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
791 size = type.alignment = ComputeTypeSize(_class.dataType);
794 size = type.alignment = sizeof(Instance *);
797 case pointerType: case subClassType: size = type.alignment = sizeof(void *); break;
799 if(type.arraySizeExp)
801 ProcessExpressionType(type.arraySizeExp);
802 ComputeExpression(type.arraySizeExp);
803 if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType &&
804 (type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
806 Location oldLoc = yylloc;
807 // bool isConstant = type.arraySizeExp.isConstant;
808 char expression[10240];
809 expression[0] = '\0';
810 type.arraySizeExp.expType = null;
811 yylloc = type.arraySizeExp.loc;
813 PrintExpression(type.arraySizeExp, expression);
814 Compiler_Error($"Array size not constant int (%s)\n", expression);
817 GetInt(type.arraySizeExp, &type.arraySize);
825 else if(type.enumClass)
827 if(type.enumClass && type.enumClass.registered && type.enumClass.registered.type == enumClass)
829 type.arraySize = eClass_GetProperty(type.enumClass.registered, "enumSize");
836 // Unimplemented auto size
840 size = ComputeTypeSize(type.type) * type.arraySize;
841 type.alignment = type.type.alignment;
847 for(member = type.members.first; member; member = member.next)
849 uint addSize = ComputeTypeSize(member);
851 member.offset = size;
852 if(member.alignment && size % member.alignment)
853 member.offset += member.alignment - (size % member.alignment);
854 size = member.offset;
856 type.alignment = Max(type.alignment, member.alignment);
859 if(type.alignment && size % type.alignment)
860 size += type.alignment - (size % type.alignment);
866 for(member = type.members.first; member; member = member.next)
868 uint addSize = ComputeTypeSize(member);
870 member.offset = size;
871 if(member.alignment && size % member.alignment)
872 member.offset += member.alignment - (size % member.alignment);
873 size = member.offset;
875 type.alignment = Max(type.alignment, member.alignment);
876 size = Max(size, addSize);
878 if(type.alignment && size % type.alignment)
879 size += type.alignment - (size % type.alignment);
884 TemplateParameter param = type.templateParameter;
885 Type baseType = ProcessTemplateParameterType(param);
887 size = ComputeTypeSize(baseType);
889 size = sizeof(uint64);
894 size = sizeof(enum { test });
899 size = sizeof(void *);
904 type.computing = false;
910 /*static */int AddMembers(OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass)
912 // This function is in need of a major review when implementing private members etc.
913 DataMember topMember = isMember ? (DataMember) _class : null;
918 Context context = isMember ? null : SetupTemplatesContext(_class);
920 if(!isMember && _class.base)
922 maxSize = _class.structSize;
923 //if(_class.base.type != systemClass) // Commented out with new Instance _class
925 // DANGER: Testing this noHeadClass here...
926 if(_class.type == structClass || _class.type == noHeadClass)
927 /*totalSize = */AddMembers(declarations, _class.base, false, &totalSize, topClass);
929 maxSize -= _class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize;
933 for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
935 if(!member.isProperty)
941 if(member.dataTypeString)
943 OldList * specs = MkList(), * decls = MkList();
946 decl = SpecDeclFromString(member.dataTypeString, specs,
947 MkDeclaratorIdentifier(MkIdentifier(member.name)));
948 ListAdd(decls, MkStructDeclarator(decl, null));
949 ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, decls, null)));
952 member.dataType = ProcessType(specs, decl);
954 ReplaceThisClassSpecifiers(specs, topClass /*member._class*/);
957 Type type = ProcessType(specs, decl);
958 DeclareType(member.dataType, false, false);
962 if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
963 member.dataType._class.registered && member.dataType._class.registered.type == structClass)
964 DeclareStruct(member.dataType._class.string, false);
967 ComputeTypeSize(member.dataType);
968 size = member.dataType.size;
969 alignment = member.dataType.alignment;
973 if(totalSize % alignment)
974 totalSize += alignment - (totalSize % alignment);
983 OldList * specs = MkList(), * list = MkList();
986 AddMembers(list, (Class)member, true, &size, topClass);
988 MkStructOrUnion((member.type == unionMember)?unionSpecifier:structSpecifier, null, list));
989 ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, null, null)));
990 alignment = member.structAlignment;
994 if(totalSize % alignment)
995 totalSize += alignment - (totalSize % alignment);
1005 if(topMember && topMember.type == unionMember)
1006 *retSize = Max(*retSize, totalSize);
1008 *retSize += totalSize;
1010 else if(totalSize < maxSize && _class.type != systemClass)
1012 char sizeString[50];
1013 sprintf(sizeString, "%d", maxSize - totalSize);
1014 ListAdd(declarations,
1015 MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(CHAR)),
1016 MkListOne(MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__ecere_padding")), MkExpConstant(sizeString))), null)));
1019 FinishTemplatesContext(context);
1020 return topMember ? topMember.memberID : _class.memberID;
1023 static int DeclareMembers(Class _class, bool isMember)
1025 DataMember topMember = isMember ? (DataMember) _class : null;
1028 Context context = isMember ? null : SetupTemplatesContext(_class);
1030 if(!isMember && (_class.type == structClass || _class.type == noHeadClass) && _class.base.type != systemClass)
1031 DeclareMembers(_class.base, false);
1033 for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
1035 if(!member.isProperty)
1042 if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
1043 member.dataType._class.registered && member.dataType._class.registered.type == structClass)
1044 DeclareStruct(member.dataType._class.string, false);
1046 if(!member.dataType && member.dataTypeString)
1047 member.dataType = ProcessTypeString(member.dataTypeString, false);
1049 DeclareType(member.dataType, false, false);
1055 DeclareMembers((Class)member, true);
1062 FinishTemplatesContext(context);
1064 return topMember ? topMember.memberID : _class.memberID;
1067 void DeclareStruct(char * name, bool skipNoHead)
1069 External external = null;
1070 Symbol classSym = FindClass(name);
1072 if(!inCompiler || !classSym) return null;
1074 // We don't need any declaration for bit classes...
1075 if(classSym.registered &&
1076 (classSym.registered.type == bitClass || classSym.registered.type == unitClass || classSym.registered.type == enumClass))
1079 /*if(classSym.registered.templateClass)
1080 return DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
1083 if(classSym.registered && classSym.imported && !classSym.declaredStructSym)
1085 // Add typedef struct
1087 OldList * specifiers, * declarators;
1088 OldList * declarations = null;
1089 char structName[1024];
1090 external = (classSym.registered && classSym.registered.type == structClass) ?
1091 classSym.pointerExternal : classSym.structExternal;
1093 // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
1094 // Moved this one up because DeclareClass done later will need it
1096 classSym.declaring++;
1098 if(strchr(classSym.string, '<'))
1100 if(classSym.registered.templateClass)
1102 DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
1103 classSym.declaring--;
1109 DeclareMembers(classSym.registered, false);
1112 FullClassNameCat(structName, name, false);
1115 external = MkExternalDeclaration(null);*/
1119 classSym.declaredStructSym = true;
1121 declarations = MkList();
1123 AddMembers(declarations, classSym.registered, false, null, classSym.registered);
1125 //ListAdd(specifiers, MkSpecifier(TYPEDEF));
1126 //ListAdd(specifiers, MkStructOrUnion(structSpecifier, null, declarations));
1128 if(!declarations->count)
1130 FreeList(declarations, null);
1131 declarations = null;
1134 if(skipNoHead || declarations)
1136 if(external && external.declaration)
1138 ((Specifier)external.declaration.specifiers->first).definitions = declarations;
1140 if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1143 //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1146 if(classSym.structExternal)
1147 ast->Move(classSym.structExternal, curExternal.prev);
1148 ast->Move(classSym.pointerExternal, curExternal.prev);
1150 classSym.id = curExternal.symbol.idCode;
1151 classSym.idCode = curExternal.symbol.idCode;
1152 // external = classSym.pointerExternal;
1153 //external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1159 external = MkExternalDeclaration(null);
1161 specifiers = MkList();
1162 declarators = MkList();
1163 ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
1166 d = MkDeclaratorIdentifier(MkIdentifier(structName));
1167 ListAdd(declarators, MkInitDeclarator(d, null));
1169 external.declaration = decl = MkDeclaration(specifiers, declarators);
1170 if(decl.symbol && !decl.symbol.pointerExternal)
1171 decl.symbol.pointerExternal = external;
1173 // For simple classes, keep the declaration as the external to move around
1174 if(classSym.registered && classSym.registered.type == structClass)
1176 char className[1024];
1177 strcpy(className, "__ecereClass_");
1178 FullClassNameCat(className, classSym.string, true);
1179 MangleClassName(className);
1182 DeclareClass(classSym, className);
1184 external.symbol = classSym;
1185 classSym.pointerExternal = external;
1186 classSym.id = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1187 classSym.idCode = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1191 char className[1024];
1192 strcpy(className, "__ecereClass_");
1193 FullClassNameCat(className, classSym.string, true);
1194 MangleClassName(className);
1196 // TOFIX: TESTING THIS...
1197 classSym.structExternal = external;
1198 DeclareClass(classSym, className);
1199 external.symbol = classSym;
1203 ast->Insert(curExternal ? curExternal.prev : null, external);
1207 classSym.declaring--;
1209 else if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1211 // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
1212 // Moved this one up because DeclareClass done later will need it
1215 classSym.declaring++;
1219 if(classSym.registered)
1220 DeclareMembers(classSym.registered, false);
1223 if(classSym.registered && (classSym.registered.type == structClass || classSym.registered.type == noHeadClass))
1226 //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1229 if(classSym.structExternal)
1230 ast->Move(classSym.structExternal, curExternal.prev);
1231 ast->Move(classSym.pointerExternal, curExternal.prev);
1233 classSym.id = curExternal.symbol.idCode;
1234 classSym.idCode = curExternal.symbol.idCode;
1235 // external = classSym.pointerExternal;
1236 // external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1239 classSym.declaring--;
1244 void DeclareProperty(Property prop, char * setName, char * getName)
1246 Symbol symbol = prop.symbol;
1247 char propName[1024];
1249 strcpy(setName, "__ecereProp_");
1250 FullClassNameCat(setName, prop._class.fullName, false);
1251 strcat(setName, "_Set_");
1252 // strcat(setName, prop.name);
1253 FullClassNameCat(setName, prop.name, true);
1255 strcpy(getName, "__ecereProp_");
1256 FullClassNameCat(getName, prop._class.fullName, false);
1257 strcat(getName, "_Get_");
1258 FullClassNameCat(getName, prop.name, true);
1259 // strcat(getName, prop.name);
1261 strcpy(propName, "__ecereProp_");
1262 FullClassNameCat(propName, prop._class.fullName, false);
1263 strcat(propName, "_");
1264 FullClassNameCat(propName, prop.name, true);
1265 // strcat(propName, prop.name);
1267 // To support "char *" property
1268 MangleClassName(getName);
1269 MangleClassName(setName);
1270 MangleClassName(propName);
1272 if(prop._class.type == structClass)
1273 DeclareStruct(prop._class.fullName, false);
1275 if(!symbol || curExternal.symbol.idCode < symbol.id)
1277 bool imported = false;
1278 bool dllImport = false;
1279 if(!symbol || symbol._import)
1284 if(!prop._class.symbol)
1285 prop._class.symbol = FindClass(prop._class.fullName);
1286 classSym = prop._class.symbol;
1287 if(classSym && !classSym._import)
1289 ModuleImport module;
1291 if(prop._class.module)
1292 module = FindModule(prop._class.module);
1294 module = mainModule;
1296 classSym._import = ClassImport
1298 name = CopyString(prop._class.fullName);
1299 isRemote = prop._class.isRemote;
1301 module.classes.Add(classSym._import);
1303 symbol = prop.symbol = Symbol { };
1304 symbol._import = (ClassImport)PropertyImport
1306 name = CopyString(prop.name);
1307 isVirtual = false; //prop.isVirtual;
1308 hasSet = prop.Set ? true : false;
1309 hasGet = prop.Get ? true : false;
1312 classSym._import.properties.Add(symbol._import);
1315 if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
1321 Context context = SetupTemplatesContext(prop._class);
1322 symbol.type = ProcessTypeString(prop.dataTypeString, false);
1323 FinishTemplatesContext(context);
1329 if(!symbol.externalGet || symbol.externalGet.type == functionExternal)
1332 OldList * specifiers, * declarators;
1337 Declarator typeDecl;
1338 bool simple = false;
1340 specifiers = MkList();
1341 declarators = MkList();
1344 ListAdd(params, MkTypeName(MkListOne(MkSpecifierName /*MkClassName*/(prop._class.fullName)),
1345 MkDeclaratorIdentifier(MkIdentifier("this"))));
1347 d = MkDeclaratorIdentifier(MkIdentifier(getName));
1350 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1353 Context context = SetupTemplatesContext(prop._class);
1354 typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
1355 FinishTemplatesContext(context);
1358 // Make sure the simple _class's type is declared
1359 for(spec = specifiers->first; spec; spec = spec.next)
1361 if(spec.type == nameSpecifier /*SpecifierClass*/)
1363 if((!typeDecl || typeDecl.type == identifierDeclarator))
1365 Symbol classSym = spec.symbol; // FindClass(spec.name);
1366 symbol._class = classSym.registered;
1367 if(classSym.registered && classSym.registered.type == structClass)
1369 DeclareStruct(spec.name, false);
1377 d = PlugDeclarator(typeDecl, d);
1380 ListAdd(params, MkTypeName(specifiers,
1381 PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
1382 specifiers = MkList();
1385 d = MkDeclaratorFunction(d, params);
1389 specifiers->Insert(null, MkSpecifier(EXTERN));
1390 else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1391 specifiers->Insert(null, MkSpecifier(STATIC));
1393 ListAdd(specifiers, MkSpecifier(VOID));
1395 ListAdd(declarators, MkInitDeclarator(d, null));
1397 decl = MkDeclaration(specifiers, declarators);
1399 external = MkExternalDeclaration(decl);
1400 ast->Insert(curExternal.prev, external);
1401 external.symbol = symbol;
1402 symbol.externalGet = external;
1404 ReplaceThisClassSpecifiers(specifiers, prop._class);
1407 FreeDeclarator(typeDecl);
1411 // Move declaration higher...
1412 ast->Move(symbol.externalGet, curExternal.prev);
1419 if(!symbol.externalSet || symbol.externalSet.type == functionExternal)
1422 OldList * specifiers, * declarators;
1427 Declarator typeDecl;
1429 declarators = MkList();
1432 // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1433 if(!prop.conversion || prop._class.type == structClass)
1435 ListAdd(params, MkTypeName(MkListOne(MkSpecifierName/*MkClassName*/(prop._class.fullName)),
1436 MkDeclaratorIdentifier(MkIdentifier("this"))));
1439 specifiers = MkList();
1442 Context context = SetupTemplatesContext(prop._class);
1443 typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
1444 MkDeclaratorIdentifier(MkIdentifier("value")));
1445 FinishTemplatesContext(context);
1447 ListAdd(params, MkTypeName(specifiers, d));
1449 d = MkDeclaratorIdentifier(MkIdentifier(setName));
1452 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1453 d = MkDeclaratorFunction(d, params);
1455 // Make sure the simple _class's type is declared
1456 for(spec = specifiers->first; spec; spec = spec.next)
1458 if(spec.type == nameSpecifier /*SpecifierClass*/)
1460 if((!typeDecl || typeDecl.type == identifierDeclarator))
1462 Symbol classSym = spec.symbol; // FindClass(spec.name);
1463 symbol._class = classSym.registered;
1464 if(classSym.registered && classSym.registered.type == structClass)
1465 DeclareStruct(spec.name, false);
1470 ListAdd(declarators, MkInitDeclarator(d, null));
1472 specifiers = MkList();
1475 specifiers->Insert(null, MkSpecifier(EXTERN));
1476 else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1477 specifiers->Insert(null, MkSpecifier(STATIC));
1479 // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1480 if(!prop.conversion || prop._class.type == structClass)
1481 ListAdd(specifiers, MkSpecifier(VOID));
1483 ListAdd(specifiers, MkSpecifierName/*MkClassName*/(prop._class.fullName));
1485 decl = MkDeclaration(specifiers, declarators);
1487 external = MkExternalDeclaration(decl);
1488 ast->Insert(curExternal.prev, external);
1489 external.symbol = symbol;
1490 symbol.externalSet = external;
1492 ReplaceThisClassSpecifiers(specifiers, prop._class);
1496 // Move declaration higher...
1497 ast->Move(symbol.externalSet, curExternal.prev);
1501 // Property (for Watchers)
1502 if(!symbol.externalPtr)
1506 OldList * specifiers = MkList();
1509 specifiers->Insert(null, MkSpecifier(EXTERN));
1511 specifiers->Insert(null, MkSpecifier(STATIC));
1513 ListAdd(specifiers, MkSpecifierName("Property"));
1516 OldList * list = MkList();
1517 ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
1518 MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1522 strcpy(propName, "__ecerePropM_");
1523 FullClassNameCat(propName, prop._class.fullName, false);
1524 strcat(propName, "_");
1525 // strcat(propName, prop.name);
1526 FullClassNameCat(propName, prop.name, true);
1528 MangleClassName(propName);
1530 ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
1531 MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1533 decl = MkDeclaration(specifiers, list);
1536 external = MkExternalDeclaration(decl);
1537 ast->Insert(curExternal.prev, external);
1538 external.symbol = symbol;
1539 symbol.externalPtr = external;
1543 // Move declaration higher...
1544 ast->Move(symbol.externalPtr, curExternal.prev);
1547 symbol.id = curExternal.symbol.idCode;
1551 // ***************** EXPRESSION PROCESSING ***************************
1552 public Type Dereference(Type source)
1557 if(source.kind == pointerType || source.kind == arrayType)
1560 source.type.refCount++;
1562 else if(source.kind == classType && !strcmp(source._class.string, "String"))
1570 // Support dereferencing of no head classes for now...
1571 else if(source.kind == classType && source._class && source._class.registered && source._class.registered.type == noHeadClass)
1577 Compiler_Error($"cannot dereference type\n");
1582 static Type Reference(Type source)
1598 void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
1600 Identifier ident = member.identifiers ? member.identifiers->first : null;
1602 DataMember dataMember = null;
1603 Method method = null;
1604 bool freeType = false;
1606 yylloc = member.loc;
1612 eClass_FindNextMember(_class, curClass, curMember, subMemberStack, subMemberStackPos);
1616 dataMember = *curMember;
1622 DataMember thisMember = (DataMember)eClass_FindProperty(_class, ident.string, privateModule);
1623 DataMember _subMemberStack[256];
1624 int _subMemberStackPos = 0;
1626 // FILL MEMBER STACK
1628 thisMember = eClass_FindDataMember(_class, ident.string, privateModule, _subMemberStack, &_subMemberStackPos);
1631 dataMember = thisMember;
1632 if(curMember && thisMember.memberAccess == publicAccess)
1634 *curMember = thisMember;
1635 *curClass = thisMember._class;
1636 memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
1637 *subMemberStackPos = _subMemberStackPos;
1644 method = eClass_FindMethod(_class, ident.string, privateModule);
1645 if(method && method.type == virtualMethod)
1657 if(!dataMember.dataType && dataMember.dataTypeString)
1659 //Context context = SetupTemplatesContext(dataMember._class);
1660 Context context = SetupTemplatesContext(_class);
1661 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
1662 FinishTemplatesContext(context);
1664 type = dataMember.dataType;
1668 // This is for destination type...
1669 if(!method.dataType)
1670 ProcessMethodType(method);
1671 //DeclareMethod(method);
1672 // method.dataType = ((Symbol)method.symbol)->type;
1673 type = method.dataType;
1676 if(ident && ident.next)
1678 for(ident = ident.next; ident && type; ident = ident.next)
1680 if(type.kind == classType)
1682 dataMember = (DataMember)eClass_FindProperty(type._class.registered, ident.string, privateModule);
1684 dataMember = eClass_FindDataMember(type._class.registered, ident.string, privateModule, null, null);
1686 type = dataMember.dataType;
1688 else if(type.kind == structType || type.kind == unionType)
1691 for(memberType = type.members.first; memberType; memberType = memberType.next)
1693 if(!strcmp(memberType.name, ident.string))
1703 // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
1704 if(type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type && _class.templateArgs /* TODO: Watch out for these _class.templateClass*/)
1707 ClassTemplateParameter curParam = null;
1709 for(sClass = _class; sClass; sClass = sClass.base)
1712 if(sClass.templateClass) sClass = sClass.templateClass;
1713 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
1715 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
1717 for(sClass = sClass.base; sClass; sClass = sClass.base)
1719 if(sClass.templateClass) sClass = sClass.templateClass;
1720 id += sClass.templateParams.count;
1731 ClassTemplateArgument arg = _class.templateArgs[id];
1732 if(arg.dataTypeString)
1735 type = ProcessTypeString(arg.dataTypeString, false);
1737 if(type && _class.templateClass)
1738 type.passAsTemplate = true;
1744 exp.destType = ProcessTypeString(arg.dataTypeString, false);
1745 exp.destType.refCount++;
1751 if(type && type.kind == classType && type._class && type._class.registered && strchr(type._class.registered.fullName, '<'))
1753 Class expClass = type._class.registered;
1754 Class cClass = null;
1759 char templateString[1024];
1760 ClassTemplateParameter param;
1761 sprintf(templateString, "%s<", expClass.templateClass.fullName);
1762 for(cClass = expClass; cClass; cClass = cClass.base)
1765 if(cClass.templateClass) cClass = cClass.templateClass;
1766 for(param = cClass.templateParams.first; param; param = param.next)
1770 ClassTemplateArgument arg;
1771 for(sClass = cClass.base; sClass; sClass = sClass.base)
1773 if(sClass.templateClass) sClass = sClass.templateClass;
1774 id += sClass.templateParams.count;
1776 arg = expClass.templateArgs[id];
1778 for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
1780 ClassTemplateParameter cParam;
1781 //int p = numParams - sClass.templateParams.count;
1784 if(sClass.templateClass) sClass = sClass.templateClass;
1786 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
1788 if(nextClass.templateClass) nextClass = nextClass.templateClass;
1789 p += nextClass.templateParams.count;
1792 for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
1794 if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
1796 if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1798 arg.dataTypeString = _class.templateArgs[p].dataTypeString;
1799 arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
1811 strcat(argument, arg.name.string);
1812 strcat(argument, " = ");
1818 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
1819 char expString[1024];
1820 OldList * specs = MkList();
1821 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
1823 char * string = PrintHexUInt64(arg.expression.ui64);
1824 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
1826 ProcessExpressionType(exp);
1827 ComputeExpression(exp);
1828 expString[0] = '\0';
1829 PrintExpression(exp, expString);
1830 strcat(argument, expString);
1832 FreeExpression(exp);
1837 strcat(argument, arg.member.name);
1840 case TemplateParameterType::type:
1842 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1843 strcat(argument, arg.dataTypeString);
1849 if(paramCount) strcat(templateString, ", ");
1850 if(lastParam != p - 1)
1852 strcat(templateString, param.name);
1853 strcat(templateString, " = ");
1855 strcat(templateString, argument);
1864 int len = strlen(templateString);
1865 if(templateString[len-1] == '<')
1869 if(templateString[len-1] == '>')
1870 templateString[len++] = ' ';
1871 templateString[len++] = '>';
1873 templateString[len++] = '\0';
1876 Context context = SetupTemplatesContext(_class);
1877 if(freeType) FreeType(type);
1878 type = ProcessTypeString(templateString, false);
1880 FinishTemplatesContext(context);
1884 if(method && member.initializer && member.initializer.type == expInitializer && member.initializer.exp)
1886 ProcessExpressionType(member.initializer.exp);
1887 if(!member.initializer.exp.expType)
1891 char expString[10240];
1892 expString[0] = '\0';
1893 PrintExpression(member.initializer.exp, expString);
1894 ChangeCh(expString, '\n', ' ');
1895 Compiler_Error($"unresolved symbol used as an instance method %s\n", expString);
1898 //else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
1899 else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
1901 Compiler_Error($"incompatible instance method %s\n", ident.string);
1904 else if(member.initializer)
1907 FreeType(member.exp.destType);
1908 member.exp.destType = type;
1909 if(member.exp.destType)
1910 member.exp.destType.refCount++;
1911 ProcessExpressionType(member.exp);
1914 ProcessInitializer(member.initializer, type);
1916 if(freeType) FreeType(type);
1920 if(_class && _class.type == unitClass)
1922 if(member.initializer)
1925 FreeType(member.exp.destType);
1926 member.exp.destType = MkClassType(_class.fullName);
1927 ProcessExpressionType(member.initializer, type);
1929 Type type = MkClassType(_class.fullName);
1930 ProcessInitializer(member.initializer, type);
1936 if(member.initializer)
1938 //ProcessExpressionType(member.exp);
1939 ProcessInitializer(member.initializer, null);
1945 Compiler_Error($"couldn't find virtual method %s in class %s\n", ident.string, _class.fullName);
1949 Compiler_Error($"couldn't find member %s in class %s\n", ident.string, _class.fullName);
1951 eClass_AddDataMember(_class, ident.string, "int", 0, 0, publicAccess);
1955 Compiler_Error($"too many initializers for instantiation of class %s\n", _class.fullName);
1960 void ProcessInstantiationType(Instantiation inst)
1965 MembersInit members;
1966 Symbol classSym; // = inst._class.symbol; // FindClass(inst._class.name);
1969 /*if(!inst._class.symbol)
1970 inst._class.symbol = FindClass(inst._class.name);*/
1971 classSym = inst._class.symbol;
1972 _class = classSym ? classSym.registered : null;
1974 // DANGER: Patch for mutex not declaring its struct when not needed
1975 if(!_class || _class.type != noHeadClass)
1976 DeclareStruct(inst._class.name, false); //_class && _class.type == noHeadClass);
1978 afterExternal = afterExternal ? afterExternal : curExternal;
1981 ProcessExpressionType(inst.exp);
1983 inst.isConstant = true;
1986 DataMember curMember = null;
1987 Class curClass = null;
1988 DataMember subMemberStack[256];
1989 int subMemberStackPos = 0;
1991 for(members = inst.members->first; members; members = members.next)
1993 switch(members.type)
1995 case methodMembersInit:
1998 static uint instMethodID = 0;
1999 External external = curExternal;
2000 Context context = curContext;
2001 Declarator declarator = members.function.declarator;
2002 Identifier nameID = GetDeclId(declarator);
2003 char * unmangled = nameID ? nameID.string : null;
2005 External createdExternal = null;
2010 //members.function.dontMangle = true;
2011 strcpy(name, "__ecereInstMeth_");
2012 FullClassNameCat(name, _class ? _class.fullName : "_UNKNOWNCLASS", false);
2014 strcat(name, nameID.string);
2016 sprintf(number, "_%08d", instMethodID++);
2017 strcat(name, number);
2018 nameID.string = CopyString(name);
2021 // Do modifications here...
2024 Symbol symbol = declarator.symbol;
2025 Method method = eClass_FindMethod(_class, unmangled, privateModule);
2027 if(method && method.type == virtualMethod)
2029 symbol.method = method;
2030 ProcessMethodType(method);
2032 if(!symbol.type.thisClass)
2034 if(method.dataType.thisClass && currentClass &&
2035 eClass_IsDerived(currentClass, method.dataType.thisClass.registered))
2037 if(!currentClass.symbol)
2038 currentClass.symbol = FindClass(currentClass.fullName);
2039 symbol.type.thisClass = currentClass.symbol;
2044 _class.symbol = FindClass(_class.fullName);
2045 symbol.type.thisClass = _class.symbol;
2048 // TESTING THIS HERE:
2049 DeclareType(symbol.type, true, true);
2054 Compiler_Error($"couldn't find virtual method %s in class %s\n",
2055 unmangled, classSym.string);
2059 //declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
2060 createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
2064 FreeSpecifier(nameID._class);
2065 nameID._class = null;
2071 Type type = declarator.symbol.type;
2072 External oldExternal = curExternal;
2074 // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
2075 // *** It was commented out for problems such as
2077 class VirtualDesktop : Window
2079 clientSize = Size { };
2090 // Commented Out: Good for bet.ec in Poker (Otherwise: obj\bet.c:187: error: `currentBet' undeclared (first use in this function))
2092 declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
2095 if(strcmp(declarator.symbol.string, name))
2097 printf("TOCHECK: Look out for this\n");
2098 delete declarator.symbol.string;
2099 declarator.symbol.string = CopyString(name);
2102 if(!declarator.symbol.parent && globalContext.symbols.root != (BTNode)declarator.symbol)
2104 printf("TOCHECK: Will this ever be in a list? Yes.\n");
2105 excludedSymbols->Remove(declarator.symbol);
2106 globalContext.symbols.Add((BTNode)declarator.symbol);
2107 if(strstr(declarator.symbol.string), "::")
2108 globalContext.hasNameSpace = true;
2113 //curExternal = curExternal.prev;
2114 //afterExternal = afterExternal->next;
2116 //ProcessFunction(afterExternal->function);
2118 //curExternal = afterExternal;
2120 External externalDecl;
2121 externalDecl = MkExternalDeclaration(null);
2122 ast->Insert(oldExternal.prev, externalDecl);
2124 // Which function does this process?
2125 if(createdExternal.function)
2127 ProcessFunction(createdExternal.function);
2129 //curExternal = oldExternal;
2132 //Declaration decl = MkDeclaration(members.function.specifiers, MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2134 Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
2135 MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2137 //externalDecl = MkExternalDeclaration(decl);
2139 //***** ast->Insert(external.prev, externalDecl);
2140 //ast->Insert(curExternal.prev, externalDecl);
2141 externalDecl.declaration = decl;
2142 if(decl.symbol && !decl.symbol.pointerExternal)
2143 decl.symbol.pointerExternal = externalDecl;
2145 // Trying this out...
2146 declarator.symbol.pointerExternal = externalDecl;
2153 curExternal = declarator.symbol.pointerExternal;
2154 ProcessFunction((FunctionDefinition)members.function);
2156 curExternal = external;
2157 curContext = context;
2161 FreeClassFunction(members.function);
2163 // In this pass, turn this into a MemberInitData
2164 exp = QMkExpId(name);
2165 members.type = dataMembersInit;
2166 members.dataMembers = MkListOne(MkMemberInit(MkListOne(MkIdentifier(unmangled)), MkInitializerAssignment(exp)));
2172 case dataMembersInit:
2174 if(members.dataMembers && classSym)
2177 Location oldyyloc = yylloc;
2178 for(member = members.dataMembers->first; member; member = member.next)
2180 ProcessMemberInitData(member, classSym.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
2181 if(member.initializer && !member.initializer.isConstant)
2182 inst.isConstant = false;
2194 static void DeclareType(Type type, bool declarePointers, bool declareParams)
2196 // OPTIMIZATIONS: TESTING THIS...
2199 if(type.kind == functionType)
2204 for(param = type.params.first; param; param = param.next)
2205 DeclareType(param, declarePointers, true);
2207 DeclareType(type.returnType, declarePointers, true);
2209 else if(type.kind == pointerType && declarePointers)
2210 DeclareType(type.type, declarePointers, false);
2211 else if(type.kind == classType)
2213 if(type._class.registered && (type._class.registered.type == structClass || type._class.registered.type == noHeadClass) && !type._class.declaring)
2214 DeclareStruct(type._class.registered.fullName, type._class.registered.type == noHeadClass);
2216 else if(type.kind == structType || type.kind == unionType)
2219 for(member = type.members.first; member; member = member.next)
2220 DeclareType(member, false, false);
2222 else if(type.kind == arrayType)
2223 DeclareType(type.arrayType, declarePointers, false);
2227 ClassTemplateArgument * FindTemplateArg(Class _class, TemplateParameter param)
2229 ClassTemplateArgument * arg = null;
2231 ClassTemplateParameter curParam = null;
2233 for(sClass = _class; sClass; sClass = sClass.base)
2236 if(sClass.templateClass) sClass = sClass.templateClass;
2237 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2239 if(curParam.type == TemplateParameterType::type && !strcmp(param.identifier.string, curParam.name))
2241 for(sClass = sClass.base; sClass; sClass = sClass.base)
2243 if(sClass.templateClass) sClass = sClass.templateClass;
2244 id += sClass.templateParams.count;
2254 arg = &_class.templateArgs[id];
2255 if(arg && param.type == type)
2256 arg->dataTypeClass = eSystem_FindClass(_class.module, arg->dataTypeString);
2261 public Context SetupTemplatesContext(Class _class)
2263 Context context = PushContext();
2264 context.templateTypesOnly = true;
2265 if(_class.symbol && ((Symbol)_class.symbol).templateParams)
2267 TemplateParameter param = ((Symbol)_class.symbol).templateParams->first;
2268 for(; param; param = param.next)
2270 if(param.type == type && param.identifier)
2272 TemplatedType type { key = (uintptr)param.identifier.string, param = param };
2273 curContext.templateTypes.Add((BTNode)type);
2280 for(sClass = _class; sClass; sClass = sClass.base)
2282 ClassTemplateParameter p;
2283 for(p = sClass.templateParams.first; p; p = p.next)
2285 //OldList * specs = MkList();
2286 //Declarator decl = null;
2287 //decl = SpecDeclFromString(p.dataTypeString, specs, null);
2290 TemplateParameter param = p.param;
2294 // ADD DATA TYPE HERE...
2295 p.param = param = TemplateParameter
2297 identifier = MkIdentifier(p.name), type = p.type,
2298 dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
2301 type = TemplatedType { key = (uintptr)p.name, param = param };
2302 curContext.templateTypes.Add((BTNode)type);
2310 public void FinishTemplatesContext(Context context)
2312 PopContext(context);
2313 FreeContext(context);
2317 public void ProcessMethodType(Method method)
2319 if(!method.dataType)
2321 Context context = SetupTemplatesContext(method._class);
2323 method.dataType = ProcessTypeString(method.dataTypeString, false);
2325 FinishTemplatesContext(context);
2327 if(method.type != virtualMethod && method.dataType)
2329 if(!method.dataType.thisClass && !method.dataType.staticMethod)
2331 if(!method._class.symbol)
2332 method._class.symbol = FindClass(method._class.fullName);
2333 method.dataType.thisClass = method._class.symbol;
2337 // Why was this commented out? Working fine without now...
2340 if(method.dataType.kind == functionType && !method.dataType.staticMethod && !method.dataType.thisClass)
2341 method.dataType.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2348 char * par = strstr(type, "(");
2349 char * classOp = null;
2354 for(c = par-type-1; c >= 0; c++)
2356 if(type[c] == ':' && type[c+1] == ':')
2358 classOp = type + c - 1;
2359 for(c = c-1; c >=0 && !isspace(type[c]); c--)
2366 else if(!isspace(type[c]))
2373 int typeLen = strlen(type);
2374 memcpy(temp, classOp, classOpLen);
2375 temp[classOpLen] = '\0';
2377 _class = eSystem_FindClass(module, temp);
2380 method.dataTypeString = new char[typeLen - classOpLen + 1];
2381 memcpy(method.dataTypeString, type, classOp - type);
2382 memcpy(method.dataTypeString + (classOp - type), classOp + classOpLen, typeLen - (classOp - type + classOpLen));
2385 method.dataTypeString = type;
2391 public void ProcessPropertyType(Property prop)
2395 Context context = SetupTemplatesContext(prop._class);
2396 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2397 FinishTemplatesContext(context);
2401 public void DeclareMethod(Method method, char * name)
2403 Symbol symbol = method.symbol;
2404 if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
2406 bool imported = false;
2407 bool dllImport = false;
2409 if(!method.dataType)
2410 method.dataType = ProcessTypeString(method.dataTypeString, false);
2412 if(!symbol || symbol._import || method.type == virtualMethod)
2414 if(!symbol || method.type == virtualMethod)
2417 if(!method._class.symbol)
2418 method._class.symbol = FindClass(method._class.fullName);
2419 classSym = method._class.symbol;
2420 if(!classSym._import)
2422 ModuleImport module;
2424 if(method._class.module && method._class.module.name)
2425 module = FindModule(method._class.module);
2427 module = mainModule;
2428 classSym._import = ClassImport
2430 name = CopyString(method._class.fullName);
2431 isRemote = method._class.isRemote;
2433 module.classes.Add(classSym._import);
2437 symbol = method.symbol = Symbol { };
2441 symbol._import = (ClassImport)MethodImport
2443 name = CopyString(method.name);
2444 isVirtual = method.type == virtualMethod;
2446 classSym._import.methods.Add(symbol._import);
2450 // Set the symbol type
2454 type.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2456 else if(type.thisClass == (void *)-1)
2458 type.thisClass = null;
2461 // symbol.type = ProcessTypeString(method.dataTypeString, false);
2462 symbol.type = method.dataType;
2463 if(symbol.type) symbol.type.refCount++;
2466 if(!method.thisClass || strcmp(method.thisClass, "void"))
2467 symbol.type.params.Insert(null,
2468 MkClassType(method.thisClass ? method.thisClass : method._class.fullName));
2471 if(!method.dataType.dllExport)
2474 if(method._class.module != privateModule && method._class.module.importType != staticImport)
2480 if(!method.dataType)
2481 method.dataType = ((Symbol)method.symbol).type;
2482 //ProcessMethodType(method);
2485 if(method.type != virtualMethod && method.dataType)
2486 DeclareType(method.dataType, true, true);
2488 if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2490 // We need a declaration here :)
2492 OldList * specifiers, * declarators;
2494 Declarator funcDecl;
2497 specifiers = MkList();
2498 declarators = MkList();
2502 ListAdd(specifiers, MkSpecifier(EXTERN));
2503 else if(method._class.symbol && ((Symbol)method._class.symbol).isStatic)
2504 ListAdd(specifiers, MkSpecifier(STATIC));
2506 if(method.type == virtualMethod)
2508 ListAdd(specifiers, MkSpecifier(INT));
2509 d = MkDeclaratorIdentifier(MkIdentifier(name));
2513 d = MkDeclaratorIdentifier(MkIdentifier(name));
2516 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2518 Context context = SetupTemplatesContext(method._class);
2519 d = SpecDeclFromString(method.dataTypeString, specifiers, d);
2520 FinishTemplatesContext(context);
2522 funcDecl = GetFuncDecl(d);
2526 Specifier spec, next;
2527 for(spec = specifiers->first; spec; spec = next)
2530 if(spec.type == extendedSpecifier)
2532 specifiers->Remove(spec);
2533 FreeSpecifier(spec);
2538 // Add this parameter if not a static method
2539 if(method.dataType && !method.dataType.staticMethod)
2541 if(funcDecl && funcDecl.function.parameters && funcDecl.function.parameters->count)
2543 Class _class = method.dataType.thisClass ? method.dataType.thisClass.registered : method._class;
2544 TypeName thisParam = MkTypeName(MkListOne(
2545 MkSpecifierName/*MkClassName*/(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)),
2546 (_class && _class.type == systemClass) ? MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("this"))) : MkDeclaratorIdentifier(MkIdentifier("this")));
2547 TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
2548 Specifier firstSpec = firstParam.qualifiers ? firstParam.qualifiers->first : null;
2550 if(firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
2552 TypeName param = funcDecl.function.parameters->first;
2553 funcDecl.function.parameters->Remove(param);
2554 FreeTypeName(param);
2557 if(!funcDecl.function.parameters)
2558 funcDecl.function.parameters = MkList();
2559 funcDecl.function.parameters->Insert(null, thisParam);
2562 // Make sure we don't have empty parameter declarations for static methods...
2564 else if(!funcDecl.function.parameters)
2566 funcDecl.function.parameters = MkList();
2567 funcDecl.function.parameters->Insert(null,
2568 MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2572 ProcessDeclarator(d);
2574 ListAdd(declarators, MkInitDeclarator(d, null));
2576 decl = MkDeclaration(specifiers, declarators);
2578 ReplaceThisClassSpecifiers(specifiers, method._class);
2580 // Keep a different symbol for the function definition than the declaration...
2581 if(symbol.pointerExternal)
2583 Symbol functionSymbol { };
2587 *functionSymbol = *symbol;
2588 functionSymbol.string = CopyString(symbol.string);
2589 if(functionSymbol.type)
2590 functionSymbol.type.refCount++;
2593 excludedSymbols->Add(functionSymbol);
2594 symbol.pointerExternal.symbol = functionSymbol;
2596 external = MkExternalDeclaration(decl);
2598 ast->Insert(curExternal ? curExternal.prev : null, external);
2599 external.symbol = symbol;
2600 symbol.pointerExternal = external;
2604 // Move declaration higher...
2605 ast->Move(symbol.pointerExternal, curExternal.prev);
2608 symbol.id = curExternal ? curExternal.symbol.idCode : MAXINT;
2612 char * ReplaceThisClass(Class _class)
2614 if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2618 ClassTemplateParameter param;
2621 char className[1024];
2622 strcpy(className, _class.fullName);
2623 for(param = _class.templateParams.first; param; param = param.next)
2625 // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2627 if(first) strcat(className, "<");
2628 if(!first) strcat(className, ", ");
2629 if(lastParam + 1 != p)
2631 strcat(className, param.name);
2632 strcat(className, " = ");
2634 strcat(className, param.name);
2642 int len = strlen(className);
2643 if(className[len-1] == '>') className[len++] = ' ';
2644 className[len++] = '>';
2645 className[len++] = '\0';
2647 return CopyString(className);
2650 return CopyString(_class.fullName);
2653 Type ReplaceThisClassType(Class _class)
2655 if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2659 ClassTemplateParameter param;
2661 char className[1024];
2662 strcpy(className, _class.fullName);
2664 for(param = _class.templateParams.first; param; param = param.next)
2666 // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2668 if(first) strcat(className, "<");
2669 if(!first) strcat(className, ", ");
2670 if(lastParam + 1 != p)
2672 strcat(className, param.name);
2673 strcat(className, " = ");
2675 strcat(className, param.name);
2683 int len = strlen(className);
2684 if(className[len-1] == '>') className[len++] = ' ';
2685 className[len++] = '>';
2686 className[len++] = '\0';
2688 return MkClassType(className);
2689 //return ProcessTypeString(className, false);
2693 return MkClassType(_class.fullName);
2694 //return ProcessTypeString(_class.fullName, false);
2698 void ReplaceThisClassSpecifiers(OldList specs, Class _class)
2700 if(specs != null && _class)
2703 for(spec = specs.first; spec; spec = spec.next)
2705 if(spec.type == baseSpecifier && spec.specifier == THISCLASS)
2707 spec.type = nameSpecifier;
2708 spec.name = ReplaceThisClass(_class);
2709 spec.symbol = FindClass(spec.name); //_class.symbol;
2715 // Returns imported or not
2716 bool DeclareFunction(GlobalFunction function, char * name)
2718 Symbol symbol = function.symbol;
2719 if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2721 bool imported = false;
2722 bool dllImport = false;
2724 if(!function.dataType)
2726 function.dataType = ProcessTypeString(function.dataTypeString, false);
2727 if(!function.dataType.thisClass)
2728 function.dataType.staticMethod = true;
2735 ModuleImport module = FindModule(function.module);
2736 // WARNING: This is not added anywhere...
2737 symbol = function.symbol = Symbol { };
2741 if(!function.dataType.dllExport)
2743 symbol._import = (ClassImport)FunctionImport { name = CopyString(function.name) };
2744 module.functions.Add(symbol._import);
2747 // Set the symbol type
2749 symbol.type = ProcessTypeString(function.dataTypeString, false);
2750 if(!symbol.type.thisClass)
2751 symbol.type.staticMethod = true;
2754 imported = symbol._import ? true : false;
2755 if(imported && function.module != privateModule && function.module.importType != staticImport)
2759 DeclareType(function.dataType, true, true);
2763 if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2765 // We need a declaration here :)
2767 OldList * specifiers, * declarators;
2769 Declarator funcDecl;
2772 specifiers = MkList();
2773 declarators = MkList();
2776 ListAdd(specifiers, MkSpecifier(EXTERN));
2779 ListAdd(specifiers, MkSpecifier(STATIC));
2782 d = MkDeclaratorIdentifier(MkIdentifier(imported ? name : function.name));
2785 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2787 d = SpecDeclFromString(function.dataTypeString, specifiers, d);
2788 // TAKE OUT THE DLL EXPORT IF STATICALLY IMPORTED:
2789 if(function.module.importType == staticImport)
2792 for(spec = specifiers->first; spec; spec = spec.next)
2793 if(spec.type == extendedSpecifier && spec.extDecl && spec.extDecl.type == extDeclString && !strcmp(spec.extDecl.s, "dllexport"))
2795 specifiers->Remove(spec);
2796 FreeSpecifier(spec);
2801 funcDecl = GetFuncDecl(d);
2803 // Make sure we don't have empty parameter declarations for static methods...
2804 if(funcDecl && !funcDecl.function.parameters)
2806 funcDecl.function.parameters = MkList();
2807 funcDecl.function.parameters->Insert(null,
2808 MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2811 ListAdd(declarators, MkInitDeclarator(d, null));
2814 Context oldCtx = curContext;
2815 curContext = globalContext;
2816 decl = MkDeclaration(specifiers, declarators);
2817 curContext = oldCtx;
2820 // Keep a different symbol for the function definition than the declaration...
2821 if(symbol.pointerExternal)
2823 Symbol functionSymbol { };
2826 *functionSymbol = *symbol;
2827 functionSymbol.string = CopyString(symbol.string);
2828 if(functionSymbol.type)
2829 functionSymbol.type.refCount++;
2832 excludedSymbols->Add(functionSymbol);
2834 symbol.pointerExternal.symbol = functionSymbol;
2836 external = MkExternalDeclaration(decl);
2838 ast->Insert(curExternal.prev, external);
2839 external.symbol = symbol;
2840 symbol.pointerExternal = external;
2844 // Move declaration higher...
2845 ast->Move(symbol.pointerExternal, curExternal.prev);
2849 symbol.id = curExternal.symbol.idCode;
2852 return (symbol && symbol._import && function.module != privateModule && function.module.importType != staticImport) ? true : false;
2855 void DeclareGlobalData(GlobalData data)
2857 Symbol symbol = data.symbol;
2858 if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2863 symbol = data.symbol = Symbol { };
2866 data.dataType = ProcessTypeString(data.dataTypeString, false);
2867 DeclareType(data.dataType, true, true);
2870 if(!symbol.pointerExternal)
2872 // We need a declaration here :)
2874 OldList * specifiers, * declarators;
2878 specifiers = MkList();
2879 declarators = MkList();
2881 ListAdd(specifiers, MkSpecifier(EXTERN));
2882 d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
2883 d = SpecDeclFromString(data.dataTypeString, specifiers, d);
2885 ListAdd(declarators, MkInitDeclarator(d, null));
2887 decl = MkDeclaration(specifiers, declarators);
2888 external = MkExternalDeclaration(decl);
2890 ast->Insert(curExternal.prev, external);
2891 external.symbol = symbol;
2892 symbol.pointerExternal = external;
2896 // Move declaration higher...
2897 ast->Move(symbol.pointerExternal, curExternal.prev);
2901 symbol.id = curExternal.symbol.idCode;
2906 class Conversion : struct
2908 Conversion prev, next;
2914 public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
2918 // Property convert;
2920 if(source.kind == templateType && dest.kind != templateType)
2922 Type type = ProcessTemplateParameterType(source.templateParameter);
2923 if(type) source = type;
2926 if(dest.kind == templateType && source.kind != templateType)
2928 Type type = ProcessTemplateParameterType(dest.templateParameter);
2929 if(type) dest = type;
2932 if((dest.classObjectType == typedObject && source.classObjectType != anyObject) || (dest.classObjectType == anyObject && source.classObjectType != typedObject))
2937 if(source.classObjectType == anyObject && dest.classObjectType != typedObject)
2942 if((dest.kind == structType && source.kind == structType) ||
2943 (dest.kind == unionType && source.kind == unionType))
2945 if((dest.enumName && source.enumName && !strcmp(dest.enumName, source.enumName)) ||
2946 (source.members.first && source.members.first == dest.members.first))
2950 if(dest.kind == ellipsisType && source.kind != voidType)
2953 if(dest.kind == pointerType && dest.type.kind == voidType &&
2954 ((source.kind == classType && (!source._class || !source._class.registered || source._class.registered.type == structClass || source._class.registered.type == normalClass || source._class.registered.type == noHeadClass || source._class.registered.type == systemClass))
2955 || source.kind == subClassType || source.kind == pointerType || source.kind == arrayType || source.kind == functionType || source.kind == thisClassType)
2957 /*source.kind != voidType && source.kind != structType && source.kind != unionType */
2959 /*&& (source.kind != classType /-*|| source._class.registered.type != structClass)*/)
2961 if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
2962 ((dest.kind == classType && (!dest._class || !dest._class.registered || dest._class.registered.type == structClass || dest._class.registered.type == normalClass || dest._class.registered.type == noHeadClass || dest._class.registered.type == systemClass))
2963 || dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
2965 /* dest.kind != voidType && dest.kind != structType && dest.kind != unionType */
2967 /*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
2970 if(((source.kind == classType && dest.kind == classType) || (source.kind == subClassType && dest.kind == subClassType)) && source._class)
2972 if(source._class.registered && source._class.registered.type == unitClass)
2974 if(conversions != null)
2976 if(source._class.registered == dest._class.registered)
2981 Class sourceBase, destBase;
2982 for(sourceBase = source._class.registered; sourceBase && sourceBase.base.type != systemClass; sourceBase = sourceBase.base);
2983 for(destBase = dest._class.registered; destBase && destBase.base.type != systemClass; destBase = destBase.base);
2984 if(sourceBase == destBase)
2988 // Don't match enum inheriting from other enum if resolving enumeration values
2989 // TESTING: !dest.classObjectType
2990 else if(source._class && dest._class && (dest.classObjectType == source.classObjectType || !dest.classObjectType) &&
2992 (!source._class.registered || source._class.registered.type != enumClass) ||
2993 (!dest._class.registered || dest._class.registered.type != enumClass)) && eClass_IsDerived(source._class.registered, dest._class.registered))
2997 // Added this so that DefinedColor = Color doesn't go through ColorRGB property
2999 dest._class && dest._class.registered && dest._class.registered.type == enumClass &&
3000 source._class && source._class.registered && source._class.registered.type != enumClass)
3002 if(eClass_IsDerived(dest._class.registered, source._class.registered))
3010 // JUST ADDED THIS...
3011 if(source.kind == subClassType && dest.kind == classType && dest._class && !strcmp(dest._class.string, "ecere::com::Class"))
3016 // Just added this for Straight conversion of ColorAlpha => Color
3017 if(source.kind == classType)
3020 for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
3023 for(convert = _class.conversions.first; convert; convert = convert.next)
3025 if(convert.memberAccess == publicAccess || _class.module == privateModule)
3027 Conversion after = (conversions != null) ? conversions.last : null;
3029 if(!convert.dataType)
3030 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3031 if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
3033 if(!conversions && !convert.Get)
3035 else if(conversions != null)
3037 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
3038 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
3039 (dest.kind != classType || dest._class.registered != _class.base))
3043 Conversion conv { convert = convert, isGet = true };
3044 // conversions.Add(conv);
3045 conversions.Insert(after, conv);
3057 if(dest.kind == classType)
3060 for(_class = dest._class ? dest._class.registered : null; _class; _class = _class.base)
3063 for(convert = _class.conversions.first; convert; convert = convert.next)
3065 if(convert.memberAccess == publicAccess || _class.module == privateModule)
3067 // Conversion after = (conversions != null) ? conversions.last : null;
3069 if(!convert.dataType)
3070 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3071 // Just added this equality check to prevent recursion.... Make it safer?
3072 // Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
3073 if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
3075 if(!conversions && !convert.Set)
3077 else if(conversions != null)
3079 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
3080 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
3081 (source.kind != classType || source._class.registered != _class.base))
3085 // *** Testing this! ***
3086 Conversion conv { convert = convert };
3087 conversions.Add(conv);
3088 //conversions.Insert(after, conv);
3096 /*if(dest._class.registered && !strcmp(dest._class.registered.name, "bool"))
3098 if(source.kind != voidType && source.kind != structType && source.kind != unionType &&
3099 (source.kind != classType || source._class.registered.type != structClass))
3103 // TESTING THIS... IS THIS OK??
3104 if(enumBaseType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3106 if(!dest._class.registered.dataType)
3107 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3108 // Only support this for classes...
3109 if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
3110 !strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
3112 if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3121 if(source.kind == classType)
3124 for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
3127 for(convert = _class.conversions.first; convert; convert = convert.next)
3129 if(convert.memberAccess == publicAccess || _class.module == privateModule)
3131 Conversion after = (conversions != null) ? conversions.last : null;
3133 if(!convert.dataType)
3134 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3135 if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
3137 if(!conversions && !convert.Get)
3139 else if(conversions != null)
3141 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
3142 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
3143 (dest.kind != classType || dest._class.registered != _class.base))
3147 Conversion conv { convert = convert, isGet = true };
3149 // conversions.Add(conv);
3150 conversions.Insert(after, conv);
3159 // TESTING THIS... IS THIS OK??
3160 if(enumBaseType && source._class && source._class.registered && source._class.registered.type == enumClass)
3162 if(!source._class.registered.dataType)
3163 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3164 if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
3172 if(source.kind == classType || source.kind == subClassType)
3174 else if(dest.kind == source.kind &&
3175 (dest.kind != structType && dest.kind != unionType &&
3176 dest.kind != functionType && dest.kind != arrayType && dest.kind != pointerType && dest.kind != methodType))
3178 // RECENTLY ADDED THESE
3179 else if(dest.kind == doubleType && source.kind == floatType)
3181 else if(dest.kind == shortType && source.kind == charType)
3183 else if(dest.kind == intType && (source.kind == shortType || source.kind == charType))
3185 else if(dest.kind == int64Type && (source.kind == shortType || source.kind == charType || source.kind == intType))
3187 else if(dest.kind == intPtrType && (source.kind == shortType || source.kind == charType || source.kind == intType))
3189 else if(source.kind == enumType &&
3190 (dest.kind == intType || dest.kind == shortType || dest.kind == charType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType))
3192 else if(dest.kind == enumType &&
3193 (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType))
3195 else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) &&
3196 ((source.kind == functionType || (source.kind == pointerType && source.type.kind == functionType) || source.kind == methodType)))
3198 Type paramSource, paramDest;
3200 if(dest.kind == methodType)
3201 owningClassDest = dest.methodClass ? dest.methodClass : dest.method._class;
3202 if(source.kind == methodType)
3203 owningClassSource = source.methodClass ? source.methodClass : source.method._class;
3205 if(dest.kind == pointerType && dest.type.kind == functionType) dest = dest.type;
3206 if(source.kind == pointerType && source.type.kind == functionType) source = source.type;
3207 if(dest.kind == methodType)
3208 dest = dest.method.dataType;
3209 if(source.kind == methodType)
3210 source = source.method.dataType;
3212 paramSource = source.params.first;
3213 if(paramSource && paramSource.kind == voidType) paramSource = null;
3214 paramDest = dest.params.first;
3215 if(paramDest && paramDest.kind == voidType) paramDest = null;
3218 if((dest.staticMethod || (!dest.thisClass && !owningClassDest)) &&
3219 !(source.staticMethod || (!source.thisClass && !owningClassSource)))
3221 // Source thisClass must be derived from destination thisClass
3222 if(!paramDest || (!(paramDest.kind == pointerType && paramDest.type && paramDest.type.kind == voidType) && (paramDest.kind != classType ||
3223 !eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource,paramDest._class.registered))))
3225 if(paramDest && paramDest.kind == classType)
3226 Compiler_Error($"method class must be derived from %s\n", paramDest._class.string);
3228 Compiler_Error($"method class should not take an object\n");
3231 paramDest = paramDest.next;
3233 else if(!dest.staticMethod && (dest.thisClass || owningClassDest))
3235 if((source.staticMethod || (!source.thisClass && !owningClassSource)))
3239 if(!paramSource || paramSource.kind != classType || !eClass_IsDerived(paramSource._class.registered,dest.thisClass.registered))
3241 Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3247 // THIS WAS BACKWARDS:
3248 // if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(owningClassDest, paramSource._class.registered)))
3249 if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(paramSource._class.registered, owningClassDest)))
3252 Compiler_Error($"%s expected to be derived from method class\n", owningClassDest.fullName);
3254 Compiler_Error($"overriding class expected to be derived from method class\n");
3258 paramSource = paramSource.next;
3264 // Source thisClass must be derived from destination thisClass
3265 if(!eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource, dest.thisClass.registered))
3267 Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3273 // THIS WAS BACKWARDS TOO??
3274 // if(source.thisClass && owningClassDest && !eClass_IsDerived(owningClassDest, source.thisClass.registered))
3275 if(source.thisClass && source.thisClass.registered && owningClassDest && !eClass_IsDerived(source.thisClass.registered, owningClassDest))
3278 Compiler_Error($"%s expected to be derived from method class\n", /*owningClass.name*/ source.thisClass.registered.fullName);
3280 //Compiler_Error($"overriding class expected to be derived from method class\n");
3288 // Source return type must be derived from destination return type
3289 if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
3291 Compiler_Warning($"incompatible return type for function\n");
3297 for(; paramDest; paramDest = paramDest.next)
3301 //Compiler_Warning($"not enough parameters\n");
3302 Compiler_Error($"not enough parameters\n");
3306 Type paramDestType = paramDest;
3307 Type paramSourceType = paramSource;
3308 Type type = paramDestType;
3310 // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
3311 if(paramDest.kind == templateType && paramDest.templateParameter.type == TemplateParameterType::type && owningClassSource &&
3312 paramSource.kind != templateType)
3315 ClassTemplateParameter curParam = null;
3317 for(sClass = owningClassSource; sClass; sClass = sClass.base)
3320 if(sClass.templateClass) sClass = sClass.templateClass;
3321 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3323 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
3325 for(sClass = sClass.base; sClass; sClass = sClass.base)
3327 if(sClass.templateClass) sClass = sClass.templateClass;
3328 id += sClass.templateParams.count;
3339 ClassTemplateArgument arg = owningClassSource.templateArgs[id];
3340 paramDestType = type = ProcessTypeString(arg.dataTypeString, false);
3344 // paramDest must be derived from paramSource
3345 if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) &&
3346 (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
3350 PrintType(paramDest, type, false, true);
3351 Compiler_Warning($"incompatible parameter %s (expected %s)\n", paramSource.name, type);
3353 if(paramDestType != paramDest)
3354 FreeType(paramDestType);
3357 if(paramDestType != paramDest)
3358 FreeType(paramDestType);
3361 paramSource = paramSource.next;
3365 Compiler_Error($"too many parameters\n");
3370 else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) && (source.kind == pointerType && source.type.kind == voidType))
3374 else if((dest.kind == pointerType || dest.kind == arrayType) &&
3375 (source.kind == arrayType || source.kind == pointerType))
3377 if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
3384 static void FreeConvert(Conversion convert)
3386 if(convert.resultType)
3387 FreeType(convert.resultType);
3390 bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type dest,
3391 char * string, OldList conversions)
3395 for(link = (BTNamedLink)nameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
3397 Class _class = link.data;
3398 if(_class.type == enumClass)
3400 OldList converts { };
3402 type.kind = classType;
3405 _class.symbol = FindClass(_class.fullName);
3406 type._class = _class.symbol;
3408 if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
3411 Class enumClass = eSystem_FindClass(privateModule, "enum");
3415 for(baseClass = _class ; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
3417 EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
3418 for(value = e.values.first; value; value = value.next)
3420 if(!strcmp(value.name, string))
3425 FreeExpContents(sourceExp);
3426 FreeType(sourceExp.expType);
3428 sourceExp.isConstant = true;
3429 sourceExp.expType = MkClassType(baseClass.fullName);
3433 sourceExp.type = constantExp;
3434 if(!strcmp(baseClass.dataTypeString, "int"))
3435 sprintf(constant, "%d",value.data);
3437 sprintf(constant, "0x%X",value.data);
3438 sourceExp.constant = CopyString(constant);
3439 //for(;baseClass.base && baseClass.base.type != systemClass; baseClass = baseClass.base);
3442 while(converts.first)
3444 Conversion convert = converts.first;
3445 converts.Remove(convert);
3446 conversions.Add(convert);
3455 converts.Free(FreeConvert);
3459 for(nameSpace = (NameSpace *)nameSpace.nameSpaces.first; nameSpace != null; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
3460 if(MatchWithEnums_NameSpace(nameSpace, sourceExp, dest, string, conversions))
3465 public bool ModuleVisibility(Module searchIn, Module searchFor)
3467 SubModule subModule;
3469 if(searchFor == searchIn)
3472 for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
3474 if(subModule.importMode == publicAccess || searchIn == searchIn.application)
3476 if(ModuleVisibility(subModule.module, searchFor))
3483 bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, char * string, OldList conversions)
3487 if(MatchWithEnums_NameSpace(mainModule.application.systemNameSpace, sourceExp, dest, string, conversions))
3489 if(MatchWithEnums_NameSpace(mainModule.application.privateNameSpace, sourceExp, dest, string, conversions))
3491 if(MatchWithEnums_NameSpace(mainModule.application.publicNameSpace, sourceExp, dest, string, conversions))
3494 for(module = mainModule.application.allModules.first; module; module = module.next)
3496 if(ModuleVisibility(mainModule, module) && MatchWithEnums_NameSpace(module.publicNameSpace, sourceExp, dest, string, conversions))
3502 bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
3504 Type source = sourceExp.expType;
3505 Type realDest = dest;
3507 if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
3510 if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
3512 if(source._class && source._class.registered && source._class.registered.type == unitClass)
3514 Class sourceBase, destBase;
3515 for(sourceBase = source._class.registered;
3516 sourceBase && sourceBase.base && sourceBase.base.type != systemClass;
3517 sourceBase = sourceBase.base);
3518 for(destBase = dest._class.registered;
3519 destBase && destBase.base && destBase.base.type != systemClass;
3520 destBase = destBase.base);
3521 //if(source._class.registered == dest._class.registered)
3522 if(sourceBase == destBase)
3531 int64 value = MAXINT;
3536 if(sourceExp.type == constantExp)
3539 value = strtoll(sourceExp.constant, null, 0);
3541 value = strtoull(sourceExp.constant, null, 0);
3543 else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
3546 value = -strtoll(sourceExp.op.exp2.constant, null, 0);
3548 value = -strtoull(sourceExp.op.exp2.constant, null, 0);
3551 if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
3552 !strcmp(source._class.registered.fullName, "ecere::com::unichar"))
3555 source = Type { kind = intType, isSigned = false, refCount = 1 };
3558 if(dest.kind == classType)
3560 Class _class = dest._class ? dest._class.registered : null;
3562 if(_class && _class.type == unitClass)
3564 if(source.kind != classType)
3567 Type tempDest, tempSource;
3569 for(; _class.base.type != systemClass; _class = _class.base);
3571 tempDest = tempType;
3573 tempType.kind = classType;
3575 _class.symbol = FindClass(_class.fullName);
3577 tempType._class = _class.symbol;
3578 tempType.truth = dest.truth;
3580 MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3582 FreeType(sourceExp.expType);
3583 sourceExp.expType = dest; dest.refCount++;
3585 //sourceExp.expType = MkClassType(_class.fullName);
3593 // Why wasn't there something like this?
3594 if(_class && _class.type == bitClass && source.kind != classType)
3596 if(!dest._class.registered.dataType)
3597 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3598 if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3601 FreeType(sourceExp.expType);
3602 source = sourceExp.expType = MkClassType(dest._class.string);
3605 //source.kind = classType;
3606 //source._class = dest._class;
3610 // Adding two enumerations
3612 if(_class && _class.type == enumClass && source.kind == classType && source._class && source._class.registered && source._class.registered.type == enumClass)
3614 if(!source._class.registered.dataType)
3615 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3616 if(!dest._class.registered.dataType)
3617 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3619 if(MatchTypes(source._class.registered.dataType, dest._class.registered.dataType, conversions, null, null, true, false, false))
3622 source = sourceExp.expType = MkClassType(dest._class.string);
3625 //source.kind = classType;
3626 //source._class = dest._class;
3630 if(_class && !strcmp(_class.fullName, "ecere::com::Class") && source.kind == pointerType && source.type && source.type.kind == charType && sourceExp.type == stringExp)
3632 OldList * specs = MkList();
3636 ReadString(string, sourceExp.string);
3637 decl = SpecDeclFromString(string, specs, null);
3639 FreeExpContents(sourceExp);
3640 FreeType(sourceExp.expType);
3642 sourceExp.type = classExp;
3643 sourceExp._classExp.specifiers = specs;
3644 sourceExp._classExp.decl = decl;
3645 sourceExp.expType = dest;
3653 else if(source.kind == classType)
3655 Class _class = source._class ? source._class.registered : null;
3657 if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass )) // TOCHECK: enumClass, bitClass is new here...
3660 if(dest.kind != classType)
3662 // Testing this simpler piece of code... (Broke Units Conversion to no unit Logic)
3663 if(!source._class.registered.dataType)
3664 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3667 dest = MkClassType(source._class.string);
3668 //if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, false, false))
3669 // dest = MkClassType(source._class.string);
3673 if(dest.kind != classType)
3676 Type tempDest, tempSource;
3678 if(!source._class.registered.dataType)
3679 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3681 for(; _class.base.type != systemClass; _class = _class.base);
3683 tempSource = tempType;
3684 tempType.kind = classType;
3685 tempType._class = FindClass(_class.fullName);
3686 tempType.truth = source.truth;
3687 tempType.classObjectType = source.classObjectType;
3690 MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3692 // PUT THIS BACK TESTING UNITS?
3693 if(conversions.last)
3695 ((Conversion)(conversions.last)).resultType = dest;
3699 FreeType(sourceExp.expType);
3700 sourceExp.expType = MkClassType(_class.fullName);
3701 sourceExp.expType.truth = source.truth;
3702 sourceExp.expType.classObjectType = source.classObjectType;
3704 // *** This if was commented out, put it back because "int a =^ Destroy()" shows up bool enum values in autocomplete ***
3706 if(!sourceExp.destType)
3708 FreeType(sourceExp.destType);
3709 sourceExp.destType = sourceExp.expType;
3710 if(sourceExp.expType)
3711 sourceExp.expType.refCount++;
3714 //source = _class.dataType;
3717 // TOCHECK: TESTING THIS NEW CODE
3718 if(!_class.dataType)
3719 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3721 dest = MkClassType(source._class.string);
3722 dest.truth = source.truth;
3723 dest.classObjectType = source.classObjectType;
3726 source = _class.dataType;
3736 if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
3746 if(source.kind == classType)
3748 Class _class = source._class.registered;
3749 if(_class.type == unitClass)
3751 if(!_class.dataType)
3752 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3753 source = _class.dataType;
3757 if(dest.kind == classType)
3759 Class _class = dest._class ? dest._class.registered : null;
3760 if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") ||
3761 (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass)) // TOCHECK: enumClass, bitClass is new here...
3763 if(_class.type == normalClass || _class.type == noHeadClass)
3765 Expression newExp { };
3766 *newExp = *sourceExp;
3767 if(sourceExp.destType) sourceExp.destType.refCount++;
3768 if(sourceExp.expType) sourceExp.expType.refCount++;
3769 sourceExp.type = castExp;
3770 sourceExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
3771 sourceExp.cast.exp = newExp;
3772 FreeType(sourceExp.expType);
3773 sourceExp.expType = null;
3774 ProcessExpressionType(sourceExp);
3776 // In Debugger, this helps with addresses (e.g. null pointers) that end up casted to a void *: keeps a classType instead of a pointerType
3779 FreeType(sourceExp.expType);
3780 sourceExp.expType = dest;
3784 if(inCompiler) FreeType(dest);
3789 if(!_class.dataType)
3790 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3792 dest = _class.dataType;
3796 // Accept lower precision types for units, since we want to keep the unit type
3797 if(dest.kind == doubleType &&
3798 (source.kind == doubleType || source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType ||
3799 source.kind == charType))
3801 specs = MkListOne(MkSpecifier(DOUBLE));
3803 else if(dest.kind == floatType &&
3804 (source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3805 source.kind == doubleType))
3807 specs = MkListOne(MkSpecifier(FLOAT));
3809 else if(dest.kind == int64Type && (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3810 source.kind == floatType || source.kind == doubleType))
3813 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3814 ListAdd(specs, MkSpecifier(INT64));
3816 else if(dest.kind == intType && (source.kind == intType || source.kind == shortType || source.kind == charType ||
3817 source.kind == floatType || source.kind == doubleType))
3820 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3821 ListAdd(specs, MkSpecifier(INT));
3823 else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == intType ||
3824 source.kind == floatType || source.kind == doubleType))
3827 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3828 ListAdd(specs, MkSpecifier(SHORT));
3830 else if(dest.kind == charType && (source.kind == charType || source.kind == shortType || source.kind == intType ||
3831 source.kind == floatType || source.kind == doubleType))
3834 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3835 ListAdd(specs, MkSpecifier(CHAR));
3844 else if(dest.kind == doubleType &&
3845 (source.kind == doubleType || source.kind == floatType || source.kind == int64Type || source.kind == intType || source.kind == enumType || source.kind == shortType ||
3846 source.kind == charType))
3848 specs = MkListOne(MkSpecifier(DOUBLE));
3850 else if(dest.kind == floatType &&
3851 (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3853 specs = MkListOne(MkSpecifier(FLOAT));
3855 else if(dest.kind == charType && (source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) &&
3856 (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
3859 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3860 ListAdd(specs, MkSpecifier(CHAR));
3862 else if(dest.kind == shortType && (source.kind == enumType || source.kind == charType || source.kind == shortType ||
3863 (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
3866 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3867 ListAdd(specs, MkSpecifier(SHORT));
3869 else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType))
3872 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3873 ListAdd(specs, MkSpecifier(INT));
3875 else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type))
3878 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3879 ListAdd(specs, MkSpecifier(INT64));
3881 else if(dest.kind == enumType &&
3882 (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3884 specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
3895 Expression newExp { };
3896 *newExp = *sourceExp;
3899 if(sourceExp.destType) sourceExp.destType.refCount++;
3900 if(sourceExp.expType) sourceExp.expType.refCount++;
3902 sourceExp.type = castExp;
3903 if(realDest.kind == classType)
3905 sourceExp.cast.typeName = QMkClass(realDest._class.string, null);
3906 FreeList(specs, FreeSpecifier);
3909 sourceExp.cast.typeName = MkTypeName(specs, null);
3910 if(newExp.type == opExp)
3912 sourceExp.cast.exp = MkExpBrackets(MkListOne(newExp));
3915 sourceExp.cast.exp = newExp;
3917 FreeType(sourceExp.expType);
3918 sourceExp.expType = null;
3919 ProcessExpressionType(sourceExp);
3922 FreeList(specs, FreeSpecifier);
3930 while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
3931 if(sourceExp.type == identifierExp)
3933 Identifier id = sourceExp.identifier;
3934 if(dest.kind == classType)
3936 if(dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3938 Class _class = dest._class.registered;
3939 Class enumClass = eSystem_FindClass(privateModule, "enum");
3942 for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
3945 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
3946 for(value = e.values.first; value; value = value.next)
3948 if(!strcmp(value.name, id.string))
3953 FreeExpContents(sourceExp);
3954 FreeType(sourceExp.expType);
3956 sourceExp.isConstant = true;
3957 sourceExp.expType = MkClassType(_class.fullName);
3961 sourceExp.type = constantExp;
3962 if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
3963 sprintf(constant, "%d",value.data);
3965 sprintf(constant, "0x%X",value.data);
3966 sourceExp.constant = CopyString(constant);
3967 //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
3976 // Loop through all enum classes
3977 if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
3984 #define TERTIARY(o, name, m, t, p) \
3985 static bool name(Expression exp, Operand op1, Operand op2, Operand op3) \
3987 exp.type = constantExp; \
3988 exp.string = p(op1.m ? op2.m : op3.m); \
3990 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3994 #define BINARY(o, name, m, t, p) \
3995 static bool name(Expression exp, Operand op1, Operand op2) \
3998 exp.type = constantExp; \
3999 exp.string = p(op1.m o value2); \
4001 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4005 #define BINARY_DIVIDE(o, name, m, t, p) \
4006 static bool name(Expression exp, Operand op1, Operand op2) \
4009 exp.type = constantExp; \
4010 exp.string = p(value2 ? (op1.m o value2) : 0); \
4012 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4016 #define UNARY(o, name, m, t, p) \
4017 static bool name(Expression exp, Operand op1) \
4019 exp.type = constantExp; \
4020 exp.string = p(o op1.m); \
4022 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
4026 #define OPERATOR_ALL(macro, o, name) \
4027 macro(o, Int##name, i, int, PrintInt) \
4028 macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4029 macro(o, Short##name, s, short, PrintShort) \
4030 macro(o, UShort##name, us, unsigned short, PrintUShort) \
4031 macro(o, Char##name, c, char, PrintChar) \
4032 macro(o, UChar##name, uc, unsigned char, PrintUChar) \
4033 macro(o, Float##name, f, float, PrintFloat) \
4034 macro(o, Double##name, d, double, PrintDouble)
4036 #define OPERATOR_INTTYPES(macro, o, name) \
4037 macro(o, Int##name, i, int, PrintInt) \
4038 macro(o, UInt##name, ui, unsigned int, PrintUInt) \
4039 macro(o, Short##name, s, short, PrintShort) \
4040 macro(o, UShort##name, us, unsigned short, PrintUShort) \
4041 macro(o, Char##name, c, char, PrintChar) \
4042 macro(o, UChar##name, uc, unsigned char, PrintUChar)
4045 // binary arithmetic
4046 OPERATOR_ALL(BINARY, +, Add)
4047 OPERATOR_ALL(BINARY, -, Sub)
4048 OPERATOR_ALL(BINARY, *, Mul)
4049 OPERATOR_ALL(BINARY_DIVIDE, /, Div)
4050 OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
4053 OPERATOR_ALL(UNARY, -, Neg)
4055 // unary arithmetic increment and decrement
4056 OPERATOR_ALL(UNARY, ++, Inc)
4057 OPERATOR_ALL(UNARY, --, Dec)
4059 // binary arithmetic assignment
4060 OPERATOR_ALL(BINARY, =, Asign)
4061 OPERATOR_ALL(BINARY, +=, AddAsign)
4062 OPERATOR_ALL(BINARY, -=, SubAsign)
4063 OPERATOR_ALL(BINARY, *=, MulAsign)
4064 OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
4065 OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
4068 OPERATOR_INTTYPES(BINARY, &, BitAnd)
4069 OPERATOR_INTTYPES(BINARY, |, BitOr)
4070 OPERATOR_INTTYPES(BINARY, ^, BitXor)
4071 OPERATOR_INTTYPES(BINARY, <<, LShift)
4072 OPERATOR_INTTYPES(BINARY, >>, RShift)
4075 OPERATOR_INTTYPES(UNARY, ~, BitNot)
4077 // binary bitwise assignment
4078 OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4079 OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4080 OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4081 OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4082 OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4084 // unary logical negation
4085 OPERATOR_INTTYPES(UNARY, !, Not)
4087 // binary logical equality
4088 OPERATOR_ALL(BINARY, ==, Equ)
4089 OPERATOR_ALL(BINARY, !=, Nqu)
4092 OPERATOR_ALL(BINARY, &&, And)
4093 OPERATOR_ALL(BINARY, ||, Or)
4095 // binary logical relational
4096 OPERATOR_ALL(BINARY, >, Grt)
4097 OPERATOR_ALL(BINARY, <, Sma)
4098 OPERATOR_ALL(BINARY, >=, GrtEqu)
4099 OPERATOR_ALL(BINARY, <=, SmaEqu)
4101 // tertiary condition operator
4102 OPERATOR_ALL(TERTIARY, ?, Cond)
4104 //Add, Sub, Mul, Div, Mod, , Neg, Inc, Dec, Asign, AddAsign, SubAsign, MulAsign, DivAsign, ModAsign, BitAnd, BitOr, BitXor, LShift, RShift, BitNot, AndAsign, OrAsign, XorAsign, LShiftAsign, RShiftAsign, Not, Equ, Nqu, And, Or, Grt, Sma, GrtEqu, SmaEqu
4105 #define OPERATOR_TABLE_ALL(name, type) \
4106 OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, type##Mod, \
4108 type##Inc, type##Dec, \
4109 type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, type##ModAsign, \
4110 type##BitAnd, type##BitOr, type##BitXor, type##LShift, type##RShift, \
4112 type##AndAsign, type##OrAsign, type##XorAsign, type##LShiftAsign, type##RShiftAsign, \
4114 type##Equ, type##Nqu, \
4115 type##And, type##Or, \
4116 type##Grt, type##Sma, type##GrtEqu, type##SmaEqu, type##Cond \
4119 #define OPERATOR_TABLE_INTTYPES(name, type) \
4120 OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, null, \
4122 type##Inc, type##Dec, \
4123 type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, null, \
4124 null, null, null, null, null, \
4126 null, null, null, null, null, \
4128 type##Equ, type##Nqu, \
4129 type##And, type##Or, \
4130 type##Grt, type##Sma, type##GrtEqu, type##SmaEqu \
4133 OPERATOR_TABLE_ALL(int, Int)
4134 OPERATOR_TABLE_ALL(uint, UInt)
4135 OPERATOR_TABLE_ALL(short, Short)
4136 OPERATOR_TABLE_ALL(ushort, UShort)
4137 OPERATOR_TABLE_INTTYPES(float, Float)
4138 OPERATOR_TABLE_INTTYPES(double, Double)
4139 OPERATOR_TABLE_ALL(char, Char)
4140 OPERATOR_TABLE_ALL(uchar, UChar)
4142 //OpTable intOps = { IntAdd, IntSub, IntMul, IntDiv, IntMod, IntExp, IntNot, IntBwn, IntOr, IntAnd, IntEqu, IntNqu, IntGrt, IntSma, IntGrtEqu, IntSmaEqu, IntNeg, IntLBitSft, IntRBitSft };
4143 //OpTable uintOps = { UIntAdd, UIntSub, UIntMul, UIntDiv, UIntMod, UIntExp, UIntNot, UIntBwn, UIntOr, UIntAnd, UIntEqu, UIntNqu, UIntGrt, UIntSma, UIntGrtEqu, UIntSmaEqu, UIntNeg, UIntLBitSft, UIntRBitSft };
4144 //OpTable shortOps = { ShortAdd, ShortSub, ShortMul, ShortDiv, ShortMod, ShortExp, ShortNot, ShortBwn, ShortOr, ShortAnd, ShortEqu, ShortNqu, ShortGrt, ShortSma, ShortGrtEqu, ShortSmaEqu, ShortNeg, ShortLBitSft, ShortRBitSft };
4145 //OpTable ushortOps = { UShortAdd, UShortSub, UShortMul, UShortDiv, UShortMod, UShortExp, UShortNot, UShortBwn, UShortOr, UShortAnd, UShortEqu, UShortNqu, UShortGrt, UShortSma, UShortGrtEqu, UShortSmaEqu, UShortNeg, UShortLBitSft, UShortRBitSft };
4146 //OpTable floatOps = { FloatAdd, FloatSub, FloatMul, FloatDiv, null, null, null, null, null, null, FloatEqu, FloatNqu, FloatGrt, FloatSma, FloatGrtEqu, FloatSmaEqu, FloatNeg, null, null };
4147 //OpTable doubleOps = { DoubleAdd, DoubleSub, DoubleMul, DoubleDiv, null, null, null, null, null, null, DoubleEqu, DoubleNqu, DoubleGrt, DoubleSma, DoubleGrtEqu, DoubleSmaEqu, DoubleNeg, null, null };
4148 //OpTable charOps = { CharAdd, CharSub, CharMul, CharDiv, CharMod, CharExp, CharNot, CharBwn, CharOr, CharAnd, CharEqu, CharNqu, CharGrt, CharSma, CharGrtEqu, CharSmaEqu, CharNeg, CharLBitSft, CharRBitSft };
4149 //OpTable ucharOps = { UCharAdd, UCharSub, UCharMul, UCharDiv, UCharMod, UCharExp, UCharNot, UCharBwn, UCharOr, UCharAnd, UCharEqu, UCharNqu, UCharGrt, UCharSma, UCharGrtEqu, UCharSmaEqu, UCharNeg, UCharLBitSft, UCharRBitSft };
4151 public void ReadString(char * output, char * string)
4153 int len = strlen(string);
4155 bool quoted = false, escaped = false;
4156 for(c = 0; c<len; c++)
4158 char ch = string[c];
4163 case 'n': output[d] = '\n'; break;
4164 case 't': output[d] = '\t'; break;
4165 case 'a': output[d] = '\a'; break;
4166 case 'b': output[d] = '\b'; break;
4167 case 'f': output[d] = '\f'; break;
4168 case 'r': output[d] = '\r'; break;
4169 case 'v': output[d] = '\v'; break;
4170 case '\\': output[d] = '\\'; break;
4171 case '\"': output[d] = '\"'; break;
4172 default: output[d++] = '\\'; output[d] = ch;
4173 //default: output[d] = ch;
4194 public Operand GetOperand(Expression exp)
4197 Type type = exp.expType;
4200 while(type.kind == classType &&
4201 type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
4203 if(!type._class.registered.dataType)
4204 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4205 type = type._class.registered.dataType;
4208 op.kind = type.kind;
4209 op.type = exp.expType;
4210 if(exp.isConstant && exp.type == constantExp)
4216 if(exp.constant[0] == '\'')
4217 op.c = exp.constant[1];
4218 else if(type.isSigned)
4220 op.c = (char)strtol(exp.constant, null, 0);
4225 op.uc = (unsigned char)strtoul(exp.constant, null, 0);
4233 op.s = (short)strtol(exp.constant, null, 0);
4238 op.us = (unsigned short)strtoul(exp.constant, null, 0);
4246 op.i = (int)strtol(exp.constant, null, 0);
4251 op.ui = (unsigned int)strtoul(exp.constant, null, 0);
4259 op.i64 = (int64)_strtoi64(exp.constant, null, 0);
4264 op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
4272 op.iptr = (intptr)_strtoi64(exp.constant, null, 0);
4277 op.uiptr = (uintptr)_strtoui64(exp.constant, null, 0);
4283 op.f = (float)strtod(exp.constant, null);
4287 op.d = (double)strtod(exp.constant, null);
4290 //case classType: For when we have operator overloading...
4291 // Pointer additions
4292 //case functionType:
4296 op.p = (unsigned char *)strtoul(exp.constant, null, 0);
4297 op.kind = pointerType;
4307 static void UnusedFunction()
4310 a.OnGetString(0,0,0);
4313 extern int __ecereVMethodID_class_OnGetString;
4316 static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberList, DataMember parentDataMember, uint offset)
4318 DataMember dataMember;
4319 for(dataMember = parentDataMember.members.first; dataMember; dataMember = dataMember.next)
4321 if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4322 PopulateInstanceProcessMember(inst, memberList, dataMember, offset + dataMember.offset);
4326 MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4328 void * ptr = inst.data + dataMember.offset + offset;
4329 char * result = null;
4330 exp.loc = member.loc = inst.loc;
4331 ((Identifier)member.identifiers->first).loc = inst.loc;
4333 if(!dataMember.dataType)
4334 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4335 type = dataMember.dataType;
4336 if(type.kind == classType)
4338 Class _class = type._class.registered;
4339 if(_class.type == enumClass)
4341 Class enumClass = eSystem_FindClass(privateModule, "enum");
4344 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4346 for(item = e.values.first; item; item = item.next)
4348 if((int)item.data == *(int *)ptr)
4356 exp.identifier = MkIdentifier(result);
4357 exp.type = identifierExp;
4358 exp.destType = MkClassType(_class.fullName);
4359 ProcessExpressionType(exp);
4363 if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4365 if(!_class.dataType)
4366 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4367 type = _class.dataType;
4376 FreeExpContents(exp);
4378 exp.constant = PrintFloat(*(float*)ptr);
4379 exp.type = constantExp;
4384 FreeExpContents(exp);
4386 exp.constant = PrintDouble(*(double*)ptr);
4387 exp.type = constantExp;
4392 FreeExpContents(exp);
4394 exp.constant = PrintInt(*(int*)ptr);
4395 exp.type = constantExp;
4400 FreeExpContents(exp);
4402 exp.constant = PrintInt64(*(int64*)ptr);
4403 exp.type = constantExp;
4408 FreeExpContents(exp);
4410 exp.constant = PrintInt64((int64)*(intptr*)ptr);
4411 exp.type = constantExp;
4415 Compiler_Error($"Unhandled type populating instance\n");
4418 ListAdd(memberList, member);
4421 if(parentDataMember.type == unionMember)
4426 void PopulateInstance(Instantiation inst)
4428 Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
4429 Class _class = classSym.registered;
4430 DataMember dataMember;
4431 OldList * memberList = MkList();
4432 inst.members = MkListOne(MkMembersInitList(memberList));
4433 for(dataMember = _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
4435 if(!dataMember.isProperty)
4437 if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4438 PopulateInstanceProcessMember(inst, memberList, dataMember, dataMember.offset);
4442 MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4444 void * ptr = inst.data + dataMember.offset;
4445 char * result = null;
4447 exp.loc = member.loc = inst.loc;
4448 ((Identifier)member.identifiers->first).loc = inst.loc;
4450 if(!dataMember.dataType)
4451 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4452 type = dataMember.dataType;
4453 if(type.kind == classType)
4455 Class _class = type._class.registered;
4456 if(_class.type == enumClass)
4458 Class enumClass = eSystem_FindClass(privateModule, "enum");
4461 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4463 for(item = e.values.first; item; item = item.next)
4465 if((int)item.data == *(int *)ptr)
4474 exp.identifier = MkIdentifier(result);
4475 exp.type = identifierExp;
4476 exp.destType = MkClassType(_class.fullName);
4477 ProcessExpressionType(exp);
4480 if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4482 if(!_class.dataType)
4483 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4484 type = _class.dataType;
4493 exp.constant = PrintFloat(*(float*)ptr);
4494 exp.type = constantExp;
4499 exp.constant = PrintDouble(*(double*)ptr);
4500 exp.type = constantExp;
4505 exp.constant = PrintInt(*(int*)ptr);
4506 exp.type = constantExp;
4511 exp.constant = PrintInt64(*(int64*)ptr);
4512 exp.type = constantExp;
4517 exp.constant = PrintInt64((int64)*(intptr*)ptr);
4518 exp.type = constantExp;
4522 Compiler_Error($"Unhandled type populating instance\n");
4525 ListAdd(memberList, member);
4531 void ComputeInstantiation(Expression exp)
4533 Instantiation inst = exp.instance;
4534 MembersInit members;
4535 Symbol classSym = inst._class ? inst._class.symbol : null; // FindClass(inst._class.name);
4536 Class _class = classSym ? classSym.registered : null;
4537 DataMember curMember = null;
4538 Class curClass = null;
4539 DataMember subMemberStack[256];
4540 int subMemberStackPos = 0;
4543 if(_class && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass ))
4545 // Don't recompute the instantiation...
4546 // Non Simple classes will have become constants by now
4550 if(_class.type == normalClass || _class.type == noHeadClass)
4551 inst.data = (byte *)eInstance_New(_class);
4553 inst.data = new0 byte[_class.structSize];
4558 for(members = inst.members->first; members; members = members.next)
4560 switch(members.type)
4562 case dataMembersInit:
4564 if(members.dataMembers)
4567 for(member = members.dataMembers->first; member; member = member.next)
4569 Identifier ident = member.identifiers ? member.identifiers->first : null;
4572 Property prop = null;
4573 DataMember dataMember = null;
4574 Method method = null;
4575 uint dataMemberOffset;
4579 eClass_FindNextMember(_class, &curClass, &curMember, subMemberStack, &subMemberStackPos);
4582 if(curMember.isProperty)
4583 prop = (Property)curMember;
4586 dataMember = curMember;
4588 // CHANGED THIS HERE
4589 eClass_FindDataMemberAndOffset(_class, dataMember.name, &dataMemberOffset, privateModule, null, null);
4590 // dataMemberOffset = dataMember.offset;
4597 prop = eClass_FindProperty(_class, ident.string, privateModule);
4601 if(prop.memberAccess == publicAccess)
4603 curMember = (DataMember)prop;
4604 curClass = prop._class;
4609 DataMember _subMemberStack[256];
4610 int _subMemberStackPos = 0;
4612 // FILL MEMBER STACK
4613 dataMember = eClass_FindDataMemberAndOffset(_class, ident.string, &dataMemberOffset, privateModule, _subMemberStack, &_subMemberStackPos);
4618 if(dataMember.memberAccess == publicAccess)
4620 curMember = dataMember;
4621 curClass = dataMember._class;
4622 memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
4623 subMemberStackPos = _subMemberStackPos;
4629 if(found && member.initializer && member.initializer.type == expInitializer)
4631 Expression value = member.initializer.exp;
4635 type = prop.dataType;
4639 if(!dataMember.dataType)
4640 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4642 type = dataMember.dataType;
4645 if(ident && ident.next)
4647 // for(; ident && type; ident = ident.next)
4648 for(ident = ident.next; ident && type; ident = ident.next)
4650 if(type.kind == classType)
4652 prop = eClass_FindProperty(type._class.registered,
4653 ident.string, privateModule);
4655 type = prop.dataType;
4658 dataMember = eClass_FindDataMemberAndOffset(type._class.registered,
4659 ident.string, &dataMemberOffset, privateModule, null, null);
4661 type = dataMember.dataType;
4664 else if(type.kind == structType || type.kind == unionType)
4667 for(memberType = type.members.first; memberType; memberType = memberType.next)
4669 if(!strcmp(memberType.name, ident.string))
4680 FreeType(value.destType);
4681 value.destType = type;
4682 if(type) type.refCount++;
4683 ComputeExpression(value);
4685 if(value && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass /*&& value.expType.kind == type.kind*/))
4687 if(type.kind == classType)
4689 Class _class = type._class.registered;
4690 if(_class.type == bitClass || _class.type == unitClass ||
4691 _class.type == enumClass)
4693 if(!_class.dataType)
4694 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4695 type = _class.dataType;
4701 void * ptr = inst.data + dataMemberOffset;
4703 if(value.type == constantExp)
4709 GetInt(value, (int*)ptr);
4714 GetInt64(value, (int64*)ptr);
4719 GetIntPtr(value, (intptr*)ptr);
4724 GetFloat(value, (float*)ptr);
4729 GetDouble(value, (double *)ptr);
4734 else if(value.type == instanceExp)
4736 if(type.kind == classType)
4738 Class _class = type._class.registered;
4739 if(_class.type == structClass)
4741 ComputeTypeSize(type);
4742 if(value.instance.data)
4743 memcpy(ptr, value.instance.data, type.size);
4750 if(value.type == instanceExp && value.instance.data)
4752 void (*Set)(void *, void *) = (void *)prop.Set;
4753 Set(inst.data, value.instance.data);
4754 PopulateInstance(inst);
4756 else if(value.type == constantExp)
4762 void (*Set)(void *, double) = (void *)prop.Set;
4763 Set(inst.data, strtod(value.constant, null) );
4768 void (*Set)(void *, float) = (void *)prop.Set;
4769 Set(inst.data, (float)(strtod(value.constant, null)));
4774 void (*Set)(void *, int) = (void *)prop.Set;
4775 Set(inst.data, strtol(value.constant, null, 0));
4780 void (*Set)(void *, int64) = (void *)prop.Set;
4781 Set(inst.data, _strtoi64(value.constant, null, 0));
4786 void (*Set)(void *, intptr) = (void *)prop.Set;
4787 Set(inst.data, (intptr)_strtoi64(value.constant, null, 0));
4792 else if(value.type == stringExp)
4795 ReadString(temp, value.string);
4796 prop.Set(inst.data, temp);
4800 else if(_class.type == unitClass)
4804 // Only support converting units to units for now...
4805 if(value.type == constantExp)
4807 if(type.kind == classType)
4809 Class _class = type._class.registered;
4810 if(_class.type == unitClass)
4812 if(!_class.dataType)
4813 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4814 type = _class.dataType;
4817 // TODO: Assuming same base type for units...
4823 float (*Set)(float) = (void *)prop.Set;
4824 GetFloat(member.initializer.exp, &fValue);
4825 exp.constant = PrintFloat(Set(fValue));
4826 exp.type = constantExp;
4832 double (*Set)(double) = (void *)prop.Set;
4833 GetDouble(member.initializer.exp, &dValue);
4834 exp.constant = PrintDouble(Set(dValue));
4835 exp.type = constantExp;
4842 else if(_class.type == bitClass)
4846 if(value.type == instanceExp && value.instance.data)
4848 unsigned int (*Set)(void *) = (void *)prop.Set;
4849 bits = Set(value.instance.data);
4851 else if(value.type == constantExp)
4857 BitMember bitMember = (BitMember) dataMember;
4860 GetInt(value, &part);
4861 bits = (bits & ~bitMember.mask);
4862 if(!bitMember.dataType)
4863 bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
4865 type = bitMember.dataType;
4867 if(type.kind == classType && type._class && type._class.registered)
4869 if(!type._class.registered.dataType)
4870 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4871 type = type._class.registered.dataType;
4878 bits |= ((char)part << bitMember.pos);
4880 bits |= ((unsigned char)part << bitMember.pos);
4884 bits |= ((short)part << bitMember.pos);
4886 bits |= ((unsigned short)part << bitMember.pos);
4891 bits |= ((int)part << bitMember.pos);
4893 bits |= ((unsigned int)part << bitMember.pos);
4897 bits |= ((int64)part << bitMember.pos);
4899 bits |= ((uint64)part << bitMember.pos);
4903 bits |= ((intptr)part << bitMember.pos);
4905 bits |= ((uintptr)part << bitMember.pos);
4913 if(_class && _class.type == unitClass)
4915 ComputeExpression(member.initializer.exp);
4916 exp.constant = member.initializer.exp.constant;
4917 exp.type = constantExp;
4919 member.initializer.exp.constant = null;
4929 if(_class && _class.type == bitClass)
4931 exp.constant = PrintHexUInt(bits);
4932 exp.type = constantExp;
4934 if(exp.type != instanceExp)
4940 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
4942 if(exp.op.op == SIZEOF)
4944 FreeExpContents(exp);
4945 exp.type = constantExp;
4946 exp.constant = PrintUInt(ComputeTypeSize(op1.type));
4957 // Provide default unary +
4958 Expression exp2 = exp.op.exp2;
4960 FreeExpContents(exp);
4961 FreeType(exp.expType);
4962 FreeType(exp.destType);
4968 if(op1.ops.Neg) { FreeExpContents(exp); op1.ops.Neg(exp, op1); }
4970 // unary arithmetic increment and decrement
4971 //OPERATOR_ALL(UNARY, ++, Inc)
4972 //OPERATOR_ALL(UNARY, --, Dec)
4975 if(op1.ops.BitNot) { FreeExpContents(exp); op1.ops.BitNot(exp, op1); }
4977 // unary logical negation
4979 if(op1.ops.Not) { FreeExpContents(exp); op1.ops.Not(exp, op1); }
4987 // binary arithmetic
4989 if(op1.ops.Add) { FreeExpContents(exp); op1.ops.Add(exp, op1, op2); }
4992 if(op1.ops.Sub) { FreeExpContents(exp); op1.ops.Sub(exp, op1, op2); }
4995 if(op1.ops.Mul) { FreeExpContents(exp); op1.ops.Mul(exp, op1, op2); }
4998 if(op1.ops.Div) { FreeExpContents(exp); op1.ops.Div(exp, op1, op2); }
5001 if(op1.ops.Mod) { FreeExpContents(exp); op1.ops.Mod(exp, op1, op2); }
5003 // binary arithmetic assignment
5004 //OPERATOR_ALL(BINARY, =, Asign)
5005 //OPERATOR_ALL(BINARY, +=, AddAsign)
5006 //OPERATOR_ALL(BINARY, -=, SubAsign)
5007 //OPERATOR_ALL(BINARY, *=, MulAsign)
5008 //OPERATOR_ALL(BINARY, /=, DivAsign)
5009 //OPERATOR_ALL(BINARY, %=, ModAsign)
5014 if(op1.ops.BitAnd) { FreeExpContents(exp); op1.ops.BitAnd(exp, op1, op2); }
5018 if(op1.ops.BitOr) { FreeExpContents(exp); op1.ops.BitOr(exp, op1, op2); }
5021 if(op1.ops.BitXor) { FreeExpContents(exp); op1.ops.BitXor(exp, op1, op2); }
5024 if(op1.ops.LShift) { FreeExpContents(exp); op1.ops.LShift(exp, op1, op2); }
5027 if(op1.ops.RShift) { FreeExpContents(exp); op1.ops.RShift(exp, op1, op2); }
5029 // binary bitwise assignment
5030 //OPERATOR_INTTYPES(BINARY, &=, AndAsign)
5031 //OPERATOR_INTTYPES(BINARY, |=, OrAsign)
5032 //OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
5033 //OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
5034 //OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
5035 // binary logical equality
5037 if(op1.ops.Equ) { FreeExpContents(exp); op1.ops.Equ(exp, op1, op2); }
5040 if(op1.ops.Nqu) { FreeExpContents(exp); op1.ops.Nqu(exp, op1, op2); }
5044 if(op1.ops.And) { FreeExpContents(exp); op1.ops.And(exp, op1, op2); }
5047 if(op1.ops.Or) { FreeExpContents(exp); op1.ops.Or(exp, op1, op2); }
5049 // binary logical relational
5051 if(op1.ops.Grt) { FreeExpContents(exp); op1.ops.Grt(exp, op1, op2); }
5054 if(op1.ops.Sma) { FreeExpContents(exp); op1.ops.Sma(exp, op1, op2); }
5057 if(op1.ops.GrtEqu) { FreeExpContents(exp); op1.ops.GrtEqu(exp, op1, op2); }
5060 if(op1.ops.SmaEqu) { FreeExpContents(exp); op1.ops.SmaEqu(exp, op1, op2); }
5067 void ComputeExpression(Expression exp)
5069 char expString[10240];
5070 expString[0] = '\0';
5072 PrintExpression(exp, expString);
5079 ComputeInstantiation(exp);
5088 Expression exp1, exp2 = null;
5092 // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
5094 ComputeExpression(exp.op.exp2);
5097 ComputeExpression(exp.op.exp1);
5100 op1 = GetOperand(exp1);
5101 if(op1.type) op1.type.refCount++;
5104 op2 = GetOperand(exp2);
5105 if(op2.type) op2.type.refCount++;
5111 op1 = GetOperand(exp1);
5112 if(op1.type) op1.type.refCount++;
5115 CallOperator(exp, exp1, exp2, op1, op2);
5122 if(exp.op.exp1 && exp.op.exp2)
5127 FreeExpContents(exp);
5128 op1.ops.BitAnd(exp, op1, op2);
5137 FreeExpContents(exp);
5138 op1.ops.Mul(exp, op1, op2);
5147 FreeExpContents(exp);
5148 op1.ops.Add(exp, op1, op2);
5153 // Provide default unary +
5154 Expression exp2 = exp.op.exp2;
5156 FreeExpContents(exp);
5157 FreeType(exp.expType);
5158 FreeType(exp.destType);
5169 FreeExpContents(exp);
5170 op1.ops.Sub(exp, op1, op2);
5177 FreeExpContents(exp);
5178 op1.ops.Neg(exp, op1);
5185 FreeExpContents(exp);
5186 op1.ops.BitNot(exp, op1);
5192 FreeExpContents(exp);
5193 op1.ops.Not(exp, op1);
5196 // Binary only operators
5200 FreeExpContents(exp);
5201 op1.ops.Div(exp, op1, op2);
5207 FreeExpContents(exp);
5208 op1.ops.Mod(exp, op1, op2);
5220 FreeExpContents(exp);
5221 op1.ops.Sma(exp, op1, op2);
5230 FreeExpContents(exp);
5231 op1.ops.Grt(exp, op1, op2);
5240 FreeExpContents(exp);
5241 op1.ops.SmaEqu(exp, op1, op2);
5250 FreeExpContents(exp);
5251 op1.ops.GrtEqu(exp, op1, op2);
5260 FreeExpContents(exp);
5261 op1.ops.Equ(exp, op1, op2);
5270 FreeExpContents(exp);
5271 op1.ops.Nqu(exp, op1, op2);
5278 FreeExpContents(exp);
5279 op1.ops.BitOr(exp, op1, op2);
5285 FreeExpContents(exp);
5286 op1.ops.BitXor(exp, op1, op2);
5294 FreeExpContents(exp);
5295 exp.type = constantExp;
5296 exp.constant = PrintUInt(ComputeTypeSize(op1.type));
5300 if(op1.type) FreeType(op1.type);
5301 if(op2.type) FreeType(op2.type);
5305 case extensionExpressionExp:
5308 for(e = exp.list->first; e; e = n)
5313 OldList * list = exp.list;
5314 ComputeExpression(e);
5315 //FreeExpContents(exp);
5316 FreeType(exp.expType);
5317 FreeType(exp.destType);
5334 exp.isConstant = true;
5336 ComputeExpression(exp.index.exp);
5337 if(!exp.index.exp.isConstant)
5338 exp.isConstant = false;
5340 for(e = exp.index.index->first; e; e = e.next)
5342 ComputeExpression(e);
5345 // Check if this type is int
5348 exp.isConstant = false;
5350 exp.expType = Dereference(exp.index.exp.expType);
5356 Expression memberExp = exp.member.exp;
5357 Identifier memberID = exp.member.member;
5360 ComputeExpression(exp.member.exp);
5361 type = exp.member.exp.expType;
5364 Class _class = (exp.member.member && exp.member.member.classSym) ? exp.member.member.classSym.registered : (((type.kind == classType || type.kind == subClassType) && type._class) ? type._class.registered : null);
5365 Property prop = null;
5366 DataMember member = null;
5367 Class convertTo = null;
5368 if(type.kind == subClassType && exp.member.exp.type == classExp)
5369 _class = eSystem_FindClass(privateModule, "ecere::com::Class");
5376 PrintType(type, string, false, true);
5377 classSym = FindClass(string);
5378 _class = classSym ? classSym.registered : null;
5381 if(exp.member.member)
5383 prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
5385 member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
5387 if(!prop && !member && _class && exp.member.member)
5389 Symbol classSym = FindClass(exp.member.member.string);
5391 _class = classSym ? classSym.registered : null;
5392 prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
5399 Type type = prop.dataType;
5400 // TODO: Assuming same base type for units...
5401 if(_class.type == unitClass)
5403 if(type.kind == classType)
5405 Class _class = type._class.registered;
5406 if(_class.type == unitClass)
5408 if(!_class.dataType)
5409 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5410 type = _class.dataType;
5418 float (*Get)(float) = (void *)prop.Get;
5419 GetFloat(exp.member.exp, &value);
5420 exp.constant = PrintFloat(Get ? Get(value) : value);
5421 exp.type = constantExp;
5427 double (*Get)(double);
5428 GetDouble(exp.member.exp, &value);
5431 Get = (void *)prop.Set;
5433 Get = (void *)prop.Get;
5434 exp.constant = PrintDouble(Get ? Get(value) : value);
5435 exp.type = constantExp;
5444 Expression value = exp.member.exp;
5447 ProcessPropertyType(prop);
5449 type = prop.dataType;
5452 // printf("Investigate this\n");
5454 else if(_class.type == structClass)
5460 Class propertyClass = type._class.registered;
5461 if(propertyClass.type == structClass && value.type == instanceExp)
5463 void (*Set)(void *, void *) = (void *)prop.Set;
5464 exp.instance = Instantiation { };
5465 exp.instance.data = new0 byte[_class.structSize];
5466 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5467 exp.instance.loc = exp.loc;
5468 exp.type = instanceExp;
5469 Set(exp.instance.data, value.instance.data);
5470 PopulateInstance(exp.instance);
5477 void (*Set)(void *, int) = (void *)prop.Set;
5479 exp.instance = Instantiation { };
5480 exp.instance.data = new0 byte[_class.structSize];
5481 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5482 exp.instance.loc = exp.loc;
5483 exp.type = instanceExp;
5485 GetInt(value, &intValue);
5487 Set(exp.instance.data, intValue);
5488 PopulateInstance(exp.instance);
5494 void (*Set)(void *, int64) = (void *)prop.Set;
5496 exp.instance = Instantiation { };
5497 exp.instance.data = new0 byte[_class.structSize];
5498 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5499 exp.instance.loc = exp.loc;
5500 exp.type = instanceExp;
5502 GetInt64(value, &intValue);
5504 Set(exp.instance.data, intValue);
5505 PopulateInstance(exp.instance);
5512 void (*Set)(void *, intptr) = (void *)prop.Set;
5514 exp.instance = Instantiation { };
5515 exp.instance.data = new0 byte[_class.structSize];
5516 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5517 exp.instance.loc = exp.loc;
5518 exp.type = instanceExp;
5520 GetIntPtr(value, &intValue);
5522 Set(exp.instance.data, intValue);
5523 PopulateInstance(exp.instance);
5529 void (*Set)(void *, double) = (void *)prop.Set;
5531 exp.instance = Instantiation { };
5532 exp.instance.data = new0 byte[_class.structSize];
5533 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5534 exp.instance.loc = exp.loc;
5535 exp.type = instanceExp;
5537 GetDouble(value, &doubleValue);
5539 Set(exp.instance.data, doubleValue);
5540 PopulateInstance(exp.instance);
5545 else if(_class.type == bitClass)
5551 Class propertyClass = type._class.registered;
5552 if(propertyClass.type == structClass && value.instance.data)
5554 unsigned int (*Set)(void *) = (void *)prop.Set;
5555 unsigned int bits = Set(value.instance.data);
5556 exp.constant = PrintHexUInt(bits);
5557 exp.type = constantExp;
5560 else if(_class.type == bitClass)
5563 unsigned int (*Set)(unsigned int) = (void *)prop.Set;
5566 GetUInt(exp.member.exp, &value);
5568 exp.constant = PrintHexUInt(bits);
5569 exp.type = constantExp;
5577 if(_class.type == bitClass)
5580 GetUInt(exp.member.exp, &value);
5586 Class _class = type._class.registered;
5587 if(_class.type == structClass)
5589 void (*Get)(unsigned int, void *) = (void *)prop.Get;
5591 exp.instance = Instantiation { };
5592 exp.instance.data = new0 byte[_class.structSize];
5593 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5594 exp.instance.loc = exp.loc;
5595 //exp.instance.fullSet = true;
5596 exp.type = instanceExp;
5597 Get(value, exp.instance.data);
5598 PopulateInstance(exp.instance);
5600 else if(_class.type == bitClass)
5602 unsigned int (*Get)(unsigned int) = (void *)prop.Get;
5603 uint64 bits = Get(value);
5604 exp.constant = PrintHexUInt64(bits);
5605 exp.type = constantExp;
5611 else if(_class.type == structClass)
5613 char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
5618 Class _class = type._class.registered;
5619 if(_class.type == structClass && value)
5621 void (*Get)(void *, void *) = (void *)prop.Get;
5623 exp.instance = Instantiation { };
5624 exp.instance.data = new0 byte[_class.structSize];
5625 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5626 exp.instance.loc = exp.loc;
5627 //exp.instance.fullSet = true;
5628 exp.type = instanceExp;
5629 Get(value, exp.instance.data);
5630 PopulateInstance(exp.instance);
5638 char * value = exp.member.exp.instance.data;
5643 Class _class = type._class.registered;
5644 if(_class.type == normalClass)
5646 void *(*Get)(void *) = (void *)prop.Get;
5648 exp.instance = Instantiation { };
5649 exp.instance._class = MkSpecifierName(_class.fullName); //MkClassName(_class.fullName);
5650 exp.type = instanceExp;
5651 exp.instance.data = Get(value, exp.instance.data);
5663 exp.isConstant = false;
5671 if(exp.type != ExpressionType::memberExp)
5673 FreeExpression(memberExp);
5674 FreeIdentifier(memberID);
5680 Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
5681 FreeExpContents(exp);
5682 exp.constant = PrintUInt(ComputeTypeSize(type));
5683 exp.type = constantExp;
5689 Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
5690 if(classSym && classSym.registered)
5692 if(classSym.registered.fixed)
5694 FreeSpecifier(exp._class);
5695 exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
5696 exp.type = constantExp;
5700 char className[1024];
5701 strcpy(className, "__ecereClass_");
5702 FullClassNameCat(className, classSym.string, true);
5703 MangleClassName(className);
5705 FreeExpContents(exp);
5706 exp.type = pointerExp;
5707 exp.member.exp = MkExpIdentifier(MkIdentifier(className));
5708 exp.member.member = MkIdentifier("structSize");
5718 if(exp.type == castExp)
5721 ComputeExpression(exp.cast.exp);
5724 if(e && exp.expType)
5727 type = exp.destType;
5730 if(type.kind == classType)
5732 Class _class = type._class.registered;
5733 if(_class && (_class.type == unitClass || _class.type == bitClass))
5735 if(!_class.dataType)
5736 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5737 type = _class.dataType;
5748 FreeExpContents(exp);
5749 exp.constant = PrintChar(value);
5750 exp.type = constantExp;
5754 unsigned char value;
5755 GetUChar(e, &value);
5756 FreeExpContents(exp);
5757 exp.constant = PrintUChar(value);
5758 exp.type = constantExp;
5765 GetShort(e, &value);
5766 FreeExpContents(exp);
5767 exp.constant = PrintShort(value);
5768 exp.type = constantExp;
5772 unsigned short value;
5773 GetUShort(e, &value);
5774 FreeExpContents(exp);
5775 exp.constant = PrintUShort(value);
5776 exp.type = constantExp;
5784 FreeExpContents(exp);
5785 exp.constant = PrintInt(value);
5786 exp.type = constantExp;
5792 FreeExpContents(exp);
5793 exp.constant = PrintUInt(value);
5794 exp.type = constantExp;
5801 GetInt64(e, &value);
5802 FreeExpContents(exp);
5803 exp.constant = PrintInt64(value);
5804 exp.type = constantExp;
5809 GetUInt64(e, &value);
5810 FreeExpContents(exp);
5811 exp.constant = PrintUInt64(value);
5812 exp.type = constantExp;
5819 GetIntPtr(e, &value);
5820 FreeExpContents(exp);
5821 exp.constant = PrintInt64((int64)value);
5822 exp.type = constantExp;
5827 GetUIntPtr(e, &value);
5828 FreeExpContents(exp);
5829 exp.constant = PrintUInt64((uint64)value);
5830 exp.type = constantExp;
5836 GetFloat(e, &value);
5837 FreeExpContents(exp);
5838 exp.constant = PrintFloat(value);
5839 exp.type = constantExp;
5845 GetDouble(e, &value);
5846 FreeExpContents(exp);
5847 exp.constant = PrintDouble(value);
5848 exp.type = constantExp;
5862 // Caring only about last expression for now...
5863 ComputeExpression(exp.cond.exp->last);
5864 if(exp.cond.elseExp)
5865 ComputeExpression(exp.cond.elseExp);
5867 ComputeExpression(exp.cond.cond);
5869 op1 = GetOperand(exp.cond.cond);
5870 if(op1.type) op1.type.refCount++;
5871 op2 = GetOperand(exp.cond.exp->last);
5872 if(op2.type) op2.type.refCount++;
5873 op3 = GetOperand(exp.cond.elseExp);
5874 if(op3.type) op3.type.refCount++;
5876 if(op1.ops.Cond) { FreeExpContents(exp); op1.ops.Cond(exp, op1, op2, op3); }
5877 if(op1.type) FreeType(op1.type);
5878 if(op2.type) FreeType(op2.type);
5879 if(op3.type) FreeType(op3.type);
5885 static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
5890 OldList converts { };
5893 if(destType.kind == voidType)
5896 if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
5900 // for(convert = converts.last; convert; convert = convert.prev)
5901 for(convert = converts.first; convert; convert = convert.next)
5903 bool empty = !(convert.isGet ? (void *)convert.convert.Get : (void *)convert.convert.Set);
5906 Expression newExp { };
5907 ClassObjectType objectType = exp.expType ? exp.expType.classObjectType : none;
5909 // TODO: Check this...
5911 newExp.destType = null;
5916 exp.type = memberExp;
5917 exp.addedThis = true;
5918 exp.member.exp = newExp;
5919 FreeType(exp.member.exp.expType);
5921 exp.member.exp.expType = MkClassType(convert.convert._class.fullName);
5922 exp.member.exp.expType.classObjectType = objectType;
5923 exp.member.member = MkIdentifier(convert.convert.dataTypeString);
5924 exp.member.memberType = propertyMember;
5925 exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5926 // TESTING THIS... for (int)degrees
5927 exp.needCast = true;
5928 if(exp.expType) exp.expType.refCount++;
5929 ApplyAnyObjectLogic(exp.member.exp);
5934 /*if(exp.isConstant)
5936 // Color { ColorRGB = [exp] };
5937 exp.type = instanceExp;
5938 exp.instance = MkInstantiation(MkSpecifierName((convert.convert._class.fullName), //MkClassName(convert.convert._class.fullName),
5939 null, MkListOne(MkMembersInitList(MkListOne(MkMemberInit(
5940 MkListOne(MkIdentifier(convert.convert.dataTypeString)), newExp)))));
5944 // If not constant, don't turn it yet into an instantiation
5945 // (Go through the deep members system first)
5946 exp.type = memberExp;
5947 exp.addedThis = true;
5948 exp.member.exp = newExp;
5950 // ADDED THIS HERE TO SOLVE PROPERTY ISSUES WITH NOHEAD CLASSES
5951 if(/*!notByReference && */newExp.expType && newExp.expType.kind == classType && newExp.expType._class && newExp.expType._class.registered &&
5952 newExp.expType._class.registered.type == noHeadClass)
5954 newExp.byReference = true;
5957 FreeType(exp.member.exp.expType);
5958 /*exp.member.exp.expType = convert.convert.dataType;
5959 if(convert.convert.dataType) convert.convert.dataType.refCount++;*/
5960 exp.member.exp.expType = null;
5961 if(convert.convert.dataType)
5963 exp.member.exp.expType = { };
5964 CopyTypeInto(exp.member.exp.expType, convert.convert.dataType);
5965 exp.member.exp.expType.refCount = 1;
5966 exp.member.exp.expType.classObjectType = objectType;
5967 ApplyAnyObjectLogic(exp.member.exp);
5970 exp.member.member = MkIdentifier(convert.convert._class.fullName);
5971 exp.member.memberType = reverseConversionMember;
5972 exp.expType = convert.resultType ? convert.resultType :
5973 MkClassType(convert.convert._class.fullName);
5974 exp.needCast = true;
5975 if(convert.resultType) convert.resultType.refCount++;
5981 FreeType(exp.expType);
5984 exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5985 exp.needCast = true;
5986 if(exp.expType) exp.expType.refCount++;
5990 exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
5991 exp.needCast = true;
5992 if(convert.resultType)
5993 convert.resultType.refCount++;
5997 if(exp.isConstant && inCompiler)
5998 ComputeExpression(exp);
6000 converts.Free(FreeConvert);
6003 if(!result && exp.expType && converts.count) // TO TEST: Added converts.count here to avoid a double warning with function type
6005 result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
6007 if(!result && exp.expType && exp.destType)
6009 if((exp.destType.kind == classType && exp.expType.kind == pointerType &&
6010 exp.expType.type.kind == classType && exp.expType.type._class == exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == structClass) ||
6011 (exp.expType.kind == classType && exp.destType.kind == pointerType &&
6012 exp.destType.type.kind == classType && exp.destType.type._class == exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass))
6016 // if(result) CheckTemplateTypes(exp);
6020 void CheckTemplateTypes(Expression exp)
6022 if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
6024 Expression newExp { };
6028 if(exp.destType) exp.destType.refCount++;
6029 if(exp.expType) exp.expType.refCount++;
6033 switch(exp.expType.kind)
6036 if(exp.destType.classObjectType)
6038 // We need to pass the address, just pass it along (Undo what was done above)
6039 if(exp.destType) exp.destType.refCount--;
6040 if(exp.expType) exp.expType.refCount--;
6045 // If we're looking for value:
6046 // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
6048 OldList * unionDefs = MkList();
6049 OldList * statements = MkList();
6050 context = PushContext();
6051 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
6052 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
6053 specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
6054 exp.type = extensionCompoundExp;
6055 exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
6056 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")), '=', newExp))));
6057 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")))));
6058 exp.compound.compound.context = context;
6059 PopContext(context);
6064 exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
6065 exp.cast.exp = MkExpBrackets(MkListOne(newExp));
6069 else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
6071 Expression newExp { };
6075 if(exp.destType) exp.destType.refCount++;
6076 if(exp.expType) exp.expType.refCount++;
6080 switch(exp.expType.kind)
6083 if(exp.destType.classObjectType)
6085 // We need to pass the address, just pass it along (Undo what was done above)
6086 if(exp.destType) exp.destType.refCount--;
6087 if(exp.expType) exp.expType.refCount--;
6092 // If we're looking for value:
6093 // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
6095 OldList * unionDefs = MkList();
6096 OldList * statements = MkList();
6097 context = PushContext();
6098 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
6099 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
6100 specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
6101 exp.type = extensionCompoundExp;
6102 exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
6103 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")), '=', newExp))));
6104 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")))));
6105 exp.compound.compound.context = context;
6106 PopContext(context);
6111 if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
6113 exp.type = bracketsExp;
6114 exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
6115 MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
6116 ProcessExpressionType(exp.list->first);
6121 exp.type = bracketsExp;
6122 exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
6123 newExp.needCast = true;
6124 ProcessExpressionType(exp.list->first);
6130 if(exp.expType.kind == templateType)
6132 Type type = ProcessTemplateParameterType(exp.expType.templateParameter);
6135 FreeType(exp.destType);
6136 FreeType(exp.expType);
6141 if(newExp.type == memberExp && newExp.member.memberType == dataMember)
6146 exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
6147 MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
6151 char typeString[1024];
6153 OldList * specs = MkList();
6154 typeString[0] = '\0';
6155 PrintType(exp.expType, typeString, false, false);
6156 decl = SpecDeclFromString(typeString, specs, null);
6159 //exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
6160 exp.cast.typeName = MkTypeName(specs, decl);
6161 exp.cast.exp = MkExpBrackets(MkListOne(newExp));
6162 exp.cast.exp.needCast = true;
6169 // TODO: The Symbol tree should be reorganized by namespaces
6171 // - Tree of all symbols within (stored without namespace)
6172 // - Tree of sub-namespaces
6174 static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
6176 int nsLen = strlen(nameSpace);
6178 // Start at the name space prefix
6179 for(symbol = (Symbol)tree.FindPrefix(nameSpace); symbol; symbol = (Symbol)((BTNode)symbol).next)
6181 char * s = symbol.string;
6182 if(!strncmp(s, nameSpace, nsLen))
6184 // This supports e.g. matching ecere::Socket to ecere::net::Socket
6187 for(c = strlen(s)-1; c >= 0; c--)
6192 if(!strcmp(namePart, name))
6194 // TODO: Error on ambiguity
6204 static Symbol FindWithNameSpace(BinaryTree tree, char * name)
6207 char nameSpace[1024];
6209 bool gotColon = false;
6211 nameSpace[0] = '\0';
6212 for(c = strlen(name)-1; c >= 0; c--)
6219 namePart = name+c+1;
6220 while(c >= 0 && name[c] == ':') c--;
6223 // Try an exact match first
6224 Symbol symbol = (Symbol)tree.FindString(name);
6228 // Namespace specified
6229 memcpy(nameSpace, name, c + 1);
6232 return ScanWithNameSpace(tree, nameSpace, namePart);
6236 // Looking for a global symbol, e.g. ::Sleep()
6237 Symbol symbol = (Symbol)tree.FindString(namePart);
6242 // Name only (no namespace specified)
6243 Symbol symbol = (Symbol)tree.FindString(namePart);
6246 return ScanWithNameSpace(tree, "", namePart);
6251 static void ProcessDeclaration(Declaration decl);
6253 /*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
6256 //Time startTime = GetTime();
6258 // Optimize this later? Do this before/less?
6260 Symbol symbol = null;
6261 // First, check if the identifier is declared inside the function
6262 //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6264 for(ctx = startContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6266 if(ctx == globalContext && !globalNameSpace && ctx.hasNameSpace)
6272 strcpy(curName, thisNameSpace);
6273 strcat(curName, "::");
6274 strcat(curName, name);
6275 // Try to resolve in current namespace first
6276 symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, curName);
6279 symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, name);
6282 symbol = (Symbol)(isStruct ? ctx.structSymbols : ctx.symbols).FindString(name);
6284 if(symbol || ctx == endContext) break;
6286 if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
6288 if(symbol.pointerExternal.type == functionExternal)
6290 FunctionDefinition function = symbol.pointerExternal.function;
6292 // Modified this recently...
6293 Context tmpContext = curContext;
6295 symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
6296 curContext = tmpContext;
6298 symbol.pointerExternal.symbol = symbol;
6301 DeclareType(symbol.type, true, true);
6303 ast->Insert(curExternal.prev, symbol.pointerExternal);
6305 symbol.id = curExternal.symbol.idCode;
6308 else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
6310 ast->Move(symbol.pointerExternal, curExternal.prev);
6311 symbol.id = curExternal.symbol.idCode;
6315 //findSymbolTotalTime += GetTime() - startTime;
6320 static void GetTypeSpecs(Type type, OldList * specs)
6322 if(!type.isSigned && type.kind != intPtrType) ListAdd(specs, MkSpecifier(UNSIGNED));
6327 if(type._class.registered)
6329 if(!type._class.registered.dataType)
6330 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
6331 GetTypeSpecs(type._class.registered.dataType, specs);
6335 case doubleType: ListAdd(specs, MkSpecifier(DOUBLE)); break;
6336 case floatType: ListAdd(specs, MkSpecifier(FLOAT)); break;
6337 case charType: ListAdd(specs, MkSpecifier(CHAR)); break;
6338 case shortType: ListAdd(specs, MkSpecifier(SHORT)); break;
6339 case int64Type: ListAdd(specs, MkSpecifier(INT64)); break;
6340 case intPtrType: ListAdd(specs, MkSpecifierName(type.isSigned ? "intptr" : "uintptr")); break;
6343 ListAdd(specs, MkSpecifier(INT)); break;
6347 // WARNING : This function expects a null terminated string since it recursively concatenate...
6348 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
6355 if(type._class && type._class.string)
6357 // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
6358 // look into merging with thisclass ?
6359 if(type.classObjectType == typedObject)
6360 strcat(string, "typed_object");
6362 strcat(string, type._class.string);
6365 if(type._class.registered)
6366 strcat(string, type._class.registered.name);
6368 strcat(string, type._class.string);
6375 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6376 if(funcType && funcType.kind == functionType)
6379 PrintType(funcType.returnType, string, false, fullName);
6380 strcat(string, "(*");
6381 if(printName || funcType.thisClass)
6383 strcat(string, " ");
6384 if(funcType.thisClass)
6386 strcat(string, funcType.thisClass.string);
6387 strcat(string, "::");
6390 strcat(string, type.name);
6392 strcat(string, ")(");
6393 for(param = funcType.params.first; param; param = param.next)
6395 PrintType(param, string, false, fullName);
6396 if(param.next) strcat(string, ", ");
6398 strcat(string, ")");
6402 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
6403 strcat(string, " *");
6407 case voidType: strcat(string, "void"); break;
6408 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
6409 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
6410 case intPtrType: strcat(string, type.isSigned ? "intptr" : "uintptr"); break;
6411 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
6412 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
6413 case floatType: strcat(string, "float"); break;
6414 case doubleType: strcat(string, "double"); break;
6418 strcat(string, "struct ");
6419 strcat(string, type.enumName);
6421 else if(type.typeName)
6423 strcat(string, type.typeName);
6428 strcat(string, "struct ");
6429 strcat(string,"(unnamed)");
6432 strcat(string, "struct {");
6433 for(member = type.members.first; member; member = member.next)
6435 PrintType(member, string, true, fullName);
6436 strcat(string,"; ");
6444 strcat(string, "union ");
6445 strcat(string, type.enumName);
6447 else if(type.typeName)
6449 strcat(string, type.typeName);
6453 strcat(string, "union ");
6454 strcat(string,"(unnamed)");
6460 strcat(string, "enum ");
6461 strcat(string, type.enumName);
6463 else if(type.typeName)
6465 strcat(string, type.typeName);
6468 strcat(string, "enum");
6475 strcat(string, "dllexport ");
6476 PrintType(type.returnType, string, false, fullName);
6477 strcat(string, " ");
6480 // DANGER: Testing This
6486 strcat(string, type.name);
6489 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
6490 if(name) name += 2; else name = type.name;
6491 strcat(string, name);
6505 strcat(string, "(");
6506 for(param = type.params.first; param; param = param.next)
6508 PrintType(param, string, true, fullName);
6509 if(param.next) strcat(string, ", ");
6511 strcat(string, ")");
6518 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6519 if(funcType && funcType.kind == functionType)
6522 PrintType(funcType.returnType, string, false, fullName);
6523 strcat(string, "(*");
6524 if(printName || funcType.thisClass)
6526 strcat(string, " ");
6527 if(funcType.thisClass)
6529 strcat(string, funcType.thisClass.string);
6530 strcat(string, "::");
6533 strcat(string, type.name);
6535 strcat(string, ")(");
6536 for(param = funcType.params.first; param; param = param.next)
6538 PrintType(param, string, false, fullName);
6539 if(param.next) strcat(string, ", ");
6541 strcat(string, ")");
6545 char baseType[1024], size[256];
6546 Type arrayType = type;
6550 while(arrayType.kind == TypeKind::arrayType)
6553 if(arrayType.enumClass)
6554 strcat(size, arrayType.enumClass.string);
6555 else if(arrayType.arraySizeExp)
6556 PrintExpression(arrayType.arraySizeExp, size);
6557 //sprintf(string, "%s[%s]", baseType, size);
6560 arrayType = arrayType.arrayType;
6562 _PrintType(arrayType, baseType, printName, printFunction, fullName);
6563 strcat(string, baseType);
6564 strcat(string, size);
6568 PrintType(type.arrayType, baseType, printName, fullName);
6570 strcpy(size, type.enumClass.string);
6571 else if(type.arraySizeExp)
6572 PrintExpression(type.arraySizeExp, size);
6573 //sprintf(string, "%s[%s]", baseType, size);
6574 strcat(string, baseType);
6575 strcat(string, "[");
6576 strcat(string, size);
6577 strcat(string, "]");
6584 strcat(string, "...");
6587 _PrintType(type.method.dataType, string, false, printFunction, fullName);
6590 strcat(string, "subclass(");
6591 strcat(string, type._class ? type._class.string : "int");
6592 strcat(string, ")");
6595 strcat(string, type.templateParameter.identifier.string);
6598 strcat(string, "thisclass");
6601 strcat(string, "__builtin_va_list");
6608 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
6610 strcat(string, " ");
6611 strcat(string, type.name);
6617 // TODO: Add a max buffer size to avoid overflows. This function is used with static size char arrays.
6619 void PrintType(Type type, char * string, bool printName, bool fullName)
6622 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6623 if(funcType && funcType.kind == functionType && type != funcType)
6625 char typeString[1024];
6628 PrintType(funcType.returnType, string, false, fullName);
6629 strcat(string, "(");
6630 _PrintType(type, string, printName, false, fullName);
6631 strcat(string, ")");
6634 strcat(string, type.name);
6640 strcat(string, "(");
6641 for(param = funcType.params.first; param; param = param.next)
6643 PrintType(param, string, true, fullName);
6644 if(param.next) strcat(string, ", ");
6646 strcat(string, ")");
6649 _PrintType(type, string, printName, true, fullName);
6650 if(type.bitFieldCount)
6653 sprintf(count, ":%d", type.bitFieldCount);
6654 strcat(string, count);
6658 static Type FindMember(Type type, char * string)
6661 for(memberType = type.members.first; memberType; memberType = memberType.next)
6663 if(!memberType.name)
6665 Type subType = FindMember(memberType, string);
6669 else if(!strcmp(memberType.name, string))
6675 Type FindMemberAndOffset(Type type, char * string, uint * offset)
6678 for(memberType = type.members.first; memberType; memberType = memberType.next)
6680 if(!memberType.name)
6682 Type subType = FindMember(memberType, string);
6685 *offset += memberType.offset;
6689 else if(!strcmp(memberType.name, string))
6691 *offset += memberType.offset;
6698 Expression ParseExpressionString(char * expression)
6700 fileInput = TempFile { };
6701 fileInput.Write(expression, 1, strlen(expression));
6702 fileInput.Seek(0, start);
6705 parsedExpression = null;
6707 expression_yyparse();
6710 return parsedExpression;
6713 static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassCheck)
6715 Identifier id = exp.identifier;
6716 Method method = null;
6717 Property prop = null;
6718 DataMember member = null;
6719 ClassProperty classProp = null;
6721 if(_class && _class.type == enumClass)
6723 NamedLink value = null;
6724 Class enumClass = eSystem_FindClass(privateModule, "enum");
6728 for(baseClass = _class; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
6730 EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
6731 for(value = e.values.first; value; value = value.next)
6733 if(!strcmp(value.name, id.string))
6740 FreeExpContents(exp);
6742 exp.type = constantExp;
6743 exp.isConstant = true;
6744 if(!strcmp(baseClass.dataTypeString, "int"))
6745 sprintf(constant, "%d",value.data);
6747 sprintf(constant, "0x%X",value.data);
6748 exp.constant = CopyString(constant);
6749 //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
6750 exp.expType = MkClassType(baseClass.fullName);
6758 if((method = eClass_FindMethod(_class, id.string, privateModule)))
6760 ProcessMethodType(method);
6767 // TOCHECK: Put it back to what it was...
6768 // methodClass = _class;
6769 methodClass = (skipIDClassCheck || (id && id._class)) ? _class : null;
6774 else if((prop = eClass_FindProperty(_class, id.string, privateModule)))
6777 ProcessPropertyType(prop);
6778 exp.expType = prop.dataType;
6779 if(prop.dataType) prop.dataType.refCount++;
6782 else if((member = eClass_FindDataMember(_class, id.string, privateModule, null, null)))
6784 if(!member.dataType)
6785 member.dataType = ProcessTypeString(member.dataTypeString, false);
6786 exp.expType = member.dataType;
6787 if(member.dataType) member.dataType.refCount++;
6790 else if((classProp = eClass_FindClassProperty(_class, id.string)))
6792 if(!classProp.dataType)
6793 classProp.dataType = ProcessTypeString(classProp.dataTypeString, false);
6795 if(classProp.constant)
6797 FreeExpContents(exp);
6799 exp.isConstant = true;
6800 if(classProp.dataType.kind == pointerType && classProp.dataType.type.kind == charType)
6802 //char constant[256];
6803 exp.type = stringExp;
6804 exp.constant = QMkString((char *)classProp.Get(_class));
6809 exp.type = constantExp;
6810 sprintf(constant, "%d",classProp.Get(_class));
6811 exp.constant = CopyString(constant);
6819 exp.expType = classProp.dataType;
6820 if(classProp.dataType) classProp.dataType.refCount++;
6826 static GlobalData ScanGlobalData(NameSpace nameSpace, char * name)
6828 BinaryTree * tree = &nameSpace.functions;
6829 GlobalData data = (GlobalData)tree->FindString(name);
6833 for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
6835 data = ScanGlobalData(child, name);
6843 static GlobalData FindGlobalData(char * name)
6846 NameSpace * nameSpace;
6847 nameSpace = globalData;
6848 for(c = 0; name[c]; c++)
6850 if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6852 NameSpace * newSpace;
6853 char * spaceName = new char[c - start + 1];
6854 strncpy(spaceName, name + start, c - start);
6855 spaceName[c-start] = '\0';
6856 newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6860 nameSpace = newSpace;
6861 if(name[c] == ':') c++;
6867 return ScanGlobalData(nameSpace, name + start);
6872 static int definedExpStackPos;
6873 static void * definedExpStack[512];
6875 // This function makes checkedExp equivalent to newExp, ending up freeing newExp
6876 void ReplaceExpContents(Expression checkedExp, Expression newExp)
6878 Expression prev = checkedExp.prev, next = checkedExp.next;
6880 FreeExpContents(checkedExp);
6881 FreeType(checkedExp.expType);
6882 FreeType(checkedExp.destType);
6884 *checkedExp = *newExp;
6888 checkedExp.prev = prev;
6889 checkedExp.next = next;
6892 void ApplyAnyObjectLogic(Expression e)
6894 Type destType = /*(e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : */e.destType;
6895 if(destType && (/*destType.classObjectType == ClassObjectType::typedObject || */destType.classObjectType == anyObject))
6897 //if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
6898 //ellipsisDestType = destType;
6901 Type type = e.expType;
6902 Class _class = null;
6903 //Type destType = e.destType;
6905 if(type.kind == classType && type._class && type._class.registered)
6907 _class = type._class.registered;
6909 else if(type.kind == subClassType)
6911 _class = FindClass("ecere::com::Class").registered;
6915 char string[1024] = "";
6918 PrintType(type, string, false, true);
6919 classSym = FindClass(string);
6920 if(classSym) _class = classSym.registered;
6923 if((_class && (_class.type == enumClass || _class.type == unitClass || _class.type == bitClass || _class.type == systemClass) && strcmp(_class.fullName, "class") && strcmp(_class.fullName, "ecere::com::Class")) || // Patched so that class isn't considered SYSTEM...
6924 (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
6925 destType.byReference)))
6927 if(!_class || strcmp(_class.fullName, "char *")) // TESTING THIS WITH NEW String class...
6929 Expression checkedExp = e, newExp;
6931 while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6933 if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6935 if(checkedExp.type == extensionCompoundExp)
6937 checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6940 checkedExp = checkedExp.list->last;
6942 else if(checkedExp.type == castExp)
6943 checkedExp = checkedExp.cast.exp;
6946 if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
6948 newExp = checkedExp.op.exp2;
6949 checkedExp.op.exp2 = null;
6950 FreeExpContents(checkedExp);
6952 if(e.expType && e.expType.passAsTemplate)
6955 ComputeTypeSize(e.expType);
6956 sprintf(size, "%d", e.expType.size);
6957 newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
6958 MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
6959 MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
6962 ReplaceExpContents(checkedExp, newExp);
6963 e.byReference = true;
6965 else if(!e.byReference || (_class && _class.type == noHeadClass)) // TESTING THIS HERE...
6967 Expression checkedExp, newExp;
6970 // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
6972 e.type == identifierExp ||
6973 (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
6974 (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
6975 (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
6978 if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
6980 Context context = PushContext();
6982 OldList * specs = MkList();
6983 char typeString[1024];
6984 Expression newExp { };
6986 typeString[0] = '\0';
6989 //if(e.destType) e.destType.refCount++;
6990 // if(exp.expType) exp.expType.refCount++;
6993 newExp.expType = null;
6995 PrintType(e.expType, typeString, false, true);
6996 decl = SpecDeclFromString(typeString, specs, null);
6997 newExp.destType = ProcessType(specs, decl);
6999 curContext = context;
7000 e.type = extensionCompoundExp;
7002 // We need a current compound for this
7006 OldList * stmts = MkList();
7007 sprintf(name, "__internalValue%03X", internalValueCounter++);
7008 if(!curCompound.compound.declarations)
7009 curCompound.compound.declarations = MkList();
7010 curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
7011 ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
7012 ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
7013 e.compound = MkCompoundStmt(null, stmts);
7016 printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
7019 e.compound = MkCompoundStmt(
7020 MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
7021 MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))),
7023 MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
7027 Type type = e.destType;
7029 CopyTypeInto(e.destType, type);
7030 e.destType.refCount = 1;
7031 e.destType.classObjectType = none;
7035 e.compound.compound.context = context;
7036 PopContext(context);
7037 curContext = context.parent;
7041 // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
7043 while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
7045 if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
7047 if(checkedExp.type == extensionCompoundExp)
7049 checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
7052 checkedExp = checkedExp.list->last;
7054 else if(checkedExp.type == castExp)
7055 checkedExp = checkedExp.cast.exp;
7058 Expression operand { };
7059 operand = *checkedExp;
7060 checkedExp.destType = null;
7061 checkedExp.expType = null;
7063 checkedExp.type = opExp;
7064 checkedExp.op.op = '&';
7065 checkedExp.op.exp1 = null;
7066 checkedExp.op.exp2 = operand;
7068 //newExp = MkExpOp(null, '&', checkedExp);
7070 //ReplaceExpContents(checkedExp, newExp);
7077 // If expression type is a simple class, make it an address
7078 // FixReference(e, true);
7081 if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
7082 (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
7083 (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
7085 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class"))
7087 return; // LEAVE THIS CASE (typed_object & :: methods 's this) TO PASS 2 FOR NOW
7091 Expression thisExp { };
7094 thisExp.prev = null;
7095 thisExp.next = null;
7098 e.type = bracketsExp;
7099 e.list = MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(thisExp))));
7100 if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && thisExp.expType._class.registered.type == noHeadClass)
7101 ((Expression)e.list->first).byReference = true;
7103 /*if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && !strcmp(thisExp.expType._class.registered.name, "class"))
7105 e.expType = thisExp.expType;
7106 e.expType.refCount++;
7111 CopyTypeInto(e.expType, thisExp.expType);
7112 e.expType.byReference = false;
7113 e.expType.refCount = 1;
7115 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
7116 (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass))
7118 e.expType.classObjectType = none;
7123 // TOFIX: Try this for a nice IDE crash!
7125 // The other way around
7128 if(destType && e.expType &&
7129 //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
7130 (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
7131 !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
7133 if(destType.kind == ellipsisType)
7135 Compiler_Error($"Unspecified type\n");
7137 else if(!(destType.truth && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass))
7139 bool byReference = e.expType.byReference;
7140 Expression thisExp { };
7142 OldList * specs = MkList();
7143 char typeString[1024]; // Watch buffer overruns
7145 ClassObjectType backupClassObjectType;
7147 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
7152 backupClassObjectType = type.classObjectType;
7154 type.classObjectType = none;
7156 typeString[0] = '\0';
7157 PrintType(type, typeString, false, true);
7158 decl = SpecDeclFromString(typeString, specs, null);
7160 type.classObjectType = backupClassObjectType;
7163 thisExp.prev = null;
7164 thisExp.next = null;
7167 if( ( type.kind == classType && type._class && type._class.registered && strcmp(type._class.registered.fullName, "ecere::com::Instance") &&
7168 (type._class.registered.type == systemClass || type._class.registered.type == bitClass ||
7169 type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
7170 (type.kind != pointerType && type.kind != arrayType && type.kind != classType) ||
7171 (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
7176 e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
7181 e.cast.typeName = MkTypeName(specs, decl);
7182 e.cast.exp = thisExp;
7183 e.byReference = true;
7186 e.destType = destType;
7188 destType.refCount++;
7193 void ProcessExpressionType(Expression exp)
7195 bool unresolved = false;
7196 Location oldyylloc = yylloc;
7197 bool notByReference = false;
7199 char debugExpString[4096];
7200 debugExpString[0] = '\0';
7201 PrintExpression(exp, debugExpString);
7203 if(!exp || exp.expType)
7206 //eSystem_Logf("%s\n", expString);
7208 // Testing this here
7214 Identifier id = exp.identifier;
7217 // DOING THIS LATER NOW...
7218 if(id._class && id._class.name)
7220 id.classSym = id._class.symbol; // FindClass(id._class.name);
7221 /* TODO: Name Space Fix ups
7223 id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
7227 /* WHY WAS THIS COMMENTED OUT? if(!strcmp(id.string, "__thisModule"))
7229 exp.expType = ProcessTypeString("Module", true);
7232 else */if(strstr(id.string, "__ecereClass") == id.string)
7234 exp.expType = ProcessTypeString("ecere::com::Class", true);
7237 else if(id._class && (id.classSym || (id._class.name && !strcmp(id._class.name, "property"))))
7239 // Added this here as well
7240 ReplaceClassMembers(exp, thisClass);
7241 if(exp.type != identifierExp)
7243 ProcessExpressionType(exp);
7247 if(id.classSym && ResolveIdWithClass(exp, id.classSym.registered, false))
7252 Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
7253 // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
7254 if(!symbol/* && exp.destType*/)
7256 if(exp.destType && CheckExpressionType(exp, exp.destType, false))
7262 ReplaceClassMembers(exp, thisClass ? thisClass : currentClass);
7263 if(exp.type != identifierExp)
7265 ProcessExpressionType(exp);
7269 // Static methods called from inside the _class
7270 else if(currentClass && !id._class)
7272 if(ResolveIdWithClass(exp, currentClass, true))
7275 symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
7279 // If we manage to resolve this symbol
7282 Type type = symbol.type;
7283 Class _class = (type && type.kind == classType && type._class) ? type._class.registered : null;
7285 if(_class && !strcmp(id.string, "this") && !type.classObjectType)
7287 Context context = SetupTemplatesContext(_class);
7288 type = ReplaceThisClassType(_class);
7289 FinishTemplatesContext(context);
7290 if(type) type.refCount = 0; // We'll be incrementing it right below...
7293 FreeSpecifier(id._class);
7296 id.string = CopyString(symbol.string);
7302 if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
7303 // Add missing cases here... enum Classes...
7304 exp.isConstant = true;
7306 // TOCHECK: Why was !strcmp(id.string, "this") commented out?
7307 if(symbol.isParam || !strcmp(id.string, "this"))
7309 if(_class && _class.type == structClass)
7310 exp.byReference = true;
7312 //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
7313 /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) &&
7314 ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) ||
7315 (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
7317 Identifier id = exp.identifier;
7318 exp.type = bracketsExp;
7319 exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(id)));
7323 if(symbol.isIterator)
7325 if(symbol.isIterator == 3)
7327 exp.type = bracketsExp;
7328 exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
7329 ((Expression)exp.list->first).op.exp2.expType = exp.expType;
7331 ProcessExpressionType(exp);
7333 else if(symbol.isIterator != 4)
7335 exp.type = memberExp;
7336 exp.member.exp = MkExpIdentifier(exp.identifier);
7337 exp.member.exp.expType = exp.expType;
7338 /*if(symbol.isIterator == 6)
7339 exp.member.member = MkIdentifier("key");
7341 exp.member.member = MkIdentifier("data");
7343 ProcessExpressionType(exp);
7350 DefinedExpression definedExp = null;
7351 if(thisNameSpace && !(id._class && !id._class.name))
7354 strcpy(name, thisNameSpace);
7356 strcat(name, id.string);
7357 definedExp = eSystem_FindDefine(privateModule, name);
7360 definedExp = eSystem_FindDefine(privateModule, id.string);
7364 for(c = 0; c<definedExpStackPos; c++)
7365 if(definedExpStack[c] == definedExp)
7367 if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
7369 Location backupYylloc = yylloc;
7370 definedExpStack[definedExpStackPos++] = definedExp;
7371 fileInput = TempFile { };
7372 fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
7373 fileInput.Seek(0, start);
7376 parsedExpression = null;
7378 expression_yyparse();
7381 yylloc = backupYylloc;
7383 if(parsedExpression)
7386 exp.type = bracketsExp;
7387 exp.list = MkListOne(parsedExpression);
7388 parsedExpression.loc = yylloc;
7389 ProcessExpressionType(exp);
7390 definedExpStackPos--;
7393 definedExpStackPos--;
7399 Compiler_Error($"Recursion in defined expression %s\n", id.string);
7405 GlobalData data = null;
7406 if(thisNameSpace && !(id._class && !id._class.name))
7409 strcpy(name, thisNameSpace);
7411 strcat(name, id.string);
7412 data = FindGlobalData(name);
7415 data = FindGlobalData(id.string);
7418 DeclareGlobalData(data);
7419 exp.expType = data.dataType;
7420 if(data.dataType) data.dataType.refCount++;
7423 id.string = CopyString(data.fullName);
7424 FreeSpecifier(id._class);
7431 GlobalFunction function = null;
7432 if(thisNameSpace && !(id._class && !id._class.name))
7435 strcpy(name, thisNameSpace);
7437 strcat(name, id.string);
7438 function = eSystem_FindFunction(privateModule, name);
7441 function = eSystem_FindFunction(privateModule, id.string);
7446 id.string = CopyString(function.name);
7449 if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
7450 strcpy(name, "__ecereFunction_");
7451 FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
7452 if(DeclareFunction(function, name))
7455 id.string = CopyString(name);
7457 exp.expType = function.dataType;
7458 if(function.dataType) function.dataType.refCount++;
7460 FreeSpecifier(id._class);
7477 if(!exp.instance._class)
7479 if(exp.destType && exp.destType.kind == classType && exp.destType._class)
7481 exp.instance._class = MkSpecifierName(exp.destType._class.string);
7491 //classSym = FindClass(exp.instance._class.fullName);
7492 //_class = classSym ? classSym.registered : null;
7494 ProcessInstantiationType(exp.instance);
7495 exp.isConstant = exp.instance.isConstant;
7498 if(_class.type == unitClass && _class.base.type != systemClass)
7501 Type destType = exp.destType;
7503 exp.destType = MkClassType(_class.base.fullName);
7504 exp.expType = MkClassType(_class.fullName);
7505 CheckExpressionType(exp, exp.destType, true);
7507 exp.destType = destType;
7509 exp.expType = MkClassType(_class.fullName);
7512 if(exp.instance._class)
7514 exp.expType = MkClassType(exp.instance._class.name);
7515 /*if(exp.expType._class && exp.expType._class.registered &&
7516 (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
7517 exp.expType.byReference = true;*/
7532 if(exp.constant[0] == '\'')
7534 if((int)((byte *)exp.constant)[1] > 127)
7537 unichar ch = UTF8GetChar(exp.constant + 1, &nb);
7538 if(nb < 2) ch = exp.constant[1];
7539 delete exp.constant;
7540 exp.constant = PrintUInt(ch);
7541 // type.kind = (ch > 0xFFFF) ? intType : shortType;
7542 type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
7543 type._class = FindClass("unichar");
7545 type.isSigned = false;
7549 type.kind = charType;
7550 type.isSigned = true;
7553 else if(strchr(exp.constant, '.'))
7555 char ch = exp.constant[strlen(exp.constant)-1];
7557 type.kind = floatType;
7559 type.kind = doubleType;
7560 type.isSigned = true;
7564 if(exp.constant[0] == '0' && exp.constant[1])
7565 type.isSigned = false;
7566 else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
7567 type.isSigned = false;
7568 else if(strtoll(exp.constant, null, 0) > MAXINT)
7569 type.isSigned = false;
7571 type.isSigned = true;
7572 type.kind = intType;
7574 exp.isConstant = true;
7580 exp.isConstant = true; // Why wasn't this constant?
7596 ProcessExpressionType(exp._new.size);
7601 type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
7603 DeclareType(exp.expType.type, false, false);
7607 ProcessExpressionType(exp._renew.size);
7608 ProcessExpressionType(exp._renew.exp);
7613 type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
7615 DeclareType(exp.expType.type, false, false);
7619 bool assign = false, boolResult = false, boolOps = false;
7620 Type type1 = null, type2 = null;
7621 bool useDestType = false, useSideType = false;
7622 Location oldyylloc = yylloc;
7623 bool useSideUnit = false;
7625 // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
7634 // Assignment Operators
7648 // boolean Operators
7650 // Expect boolean operators
7652 //boolResult = true;
7656 // Expect boolean operands
7667 // Gives boolean result
7675 // Just added these... testing
7680 // DANGER: Verify units
7685 if(exp.op.op != '*' || exp.op.exp1)
7692 /*// Implement speed etc.
7698 if(exp.op.op == '&')
7700 // Added this here earlier for Iterator address as key
7701 if(!exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == identifierExp && exp.op.exp2.identifier)
7703 Identifier id = exp.op.exp2.identifier;
7704 Symbol symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
7705 if(symbol && symbol.isIterator == 2)
7707 exp.type = memberExp;
7708 exp.member.exp = exp.op.exp2;
7709 exp.member.member = MkIdentifier("key");
7711 exp.op.exp2.expType = symbol.type;
7712 symbol.type.refCount++;
7713 ProcessExpressionType(exp);
7717 // exp.op.exp2.usage.usageRef = true;
7721 //dummy.kind = TypeDummy;
7725 if(exp.destType && exp.destType.kind == classType &&
7726 exp.destType._class && exp.destType._class.registered && useDestType &&
7728 ((exp.destType._class.registered.type == unitClass && useSideUnit) ||
7729 exp.destType._class.registered.type == enumClass ||
7730 exp.destType._class.registered.type == bitClass
7733 //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
7735 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7736 exp.op.exp1.destType = exp.destType;
7738 exp.destType.refCount++;
7742 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7743 exp.op.exp1.destType = dummy;
7747 // TESTING THIS HERE...
7748 if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
7749 ProcessExpressionType(exp.op.exp1);
7750 if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
7752 if(exp.op.exp1.destType == dummy)
7755 exp.op.exp1.destType = null;
7757 type1 = exp.op.exp1.expType;
7762 char expString[10240];
7763 expString[0] = '\0';
7764 if(exp.op.exp2.type == instanceExp && !exp.op.exp2.instance._class)
7768 exp.op.exp2.destType = exp.op.exp1.expType;
7769 if(exp.op.exp1.expType)
7770 exp.op.exp1.expType.refCount++;
7774 exp.op.exp2.destType = exp.destType;
7776 exp.destType.refCount++;
7779 if(type1) type1.refCount++;
7780 exp.expType = type1;
7785 PrintExpression(exp.op.exp2, expString);
7787 if(type1 && type1.kind == pointerType)
7789 if(exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN ||exp.op.op == MOD_ASSIGN ||exp.op.op == LEFT_ASSIGN ||exp.op.op == RIGHT_ASSIGN ||
7790 exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN)
7791 Compiler_Error($"operator %s illegal on pointer\n", exp.op.op);
7792 else if(exp.op.op == '=')
7794 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7795 exp.op.exp2.destType = type1;
7802 // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;)
7803 if(exp.op.op == MUL_ASSIGN || exp.op.op == DIV_ASSIGN ||exp.op.op == MOD_ASSIGN ||exp.op.op == LEFT_ASSIGN ||exp.op.op == RIGHT_ASSIGN/* ||
7804 exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
7807 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7808 exp.op.exp2.destType = type1;
7813 if(type1) type1.refCount++;
7814 exp.expType = type1;
7816 else if(exp.destType && exp.destType.kind == classType &&
7817 exp.destType._class && exp.destType._class.registered &&
7819 ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) ||
7820 (exp.destType._class.registered.type == enumClass && useDestType))
7823 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7824 exp.op.exp2.destType = exp.destType;
7826 exp.destType.refCount++;
7830 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7831 exp.op.exp2.destType = dummy;
7835 // TESTING THIS HERE... (DANGEROUS)
7836 if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered &&
7837 (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
7839 FreeType(exp.op.exp2.destType);
7840 exp.op.exp2.destType = type1;
7843 if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
7844 ProcessExpressionType(exp.op.exp2);
7845 if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
7847 if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
7849 if(exp.op.exp2.expType.kind == intPtrType || exp.op.exp2.expType.kind == int64Type || exp.op.exp2.expType.kind == intType || exp.op.exp2.expType.kind == shortType || exp.op.exp2.expType.kind == charType)
7851 if(exp.op.op != '=' && type1.type.kind == voidType)
7852 Compiler_Error($"void *: unknown size\n");
7854 else if(exp.op.exp2.expType.kind == pointerType || exp.op.exp2.expType.kind == arrayType || exp.op.exp2.expType.kind == functionType || exp.op.exp2.expType.kind == methodType||
7855 (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
7856 (exp.op.exp2.expType._class.registered.type == normalClass ||
7857 exp.op.exp2.expType._class.registered.type == structClass ||
7858 exp.op.exp2.expType._class.registered.type == noHeadClass)))
7860 if(exp.op.op == ADD_ASSIGN)
7861 Compiler_Error($"cannot add two pointers\n");
7863 else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType &&
7864 type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
7866 if(exp.op.op == ADD_ASSIGN)
7867 Compiler_Error($"cannot add two pointers\n");
7871 char type1String[1024];
7872 char type2String[1024];
7873 type1String[0] = '\0';
7874 type2String[0] = '\0';
7876 PrintType(exp.op.exp2.expType, type1String, false, true);
7877 PrintType(type1, type2String, false, true);
7878 ChangeCh(expString, '\n', ' ');
7879 Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1String, type2String);
7883 if(exp.op.exp2.destType == dummy)
7886 exp.op.exp2.destType = null;
7889 type2 = exp.op.exp2.expType;
7892 dummy.kind = voidType;
7894 if(exp.op.op == SIZEOF)
7901 exp.isConstant = true;
7903 // Get type of dereferenced pointer
7904 else if(exp.op.op == '*' && !exp.op.exp1)
7906 exp.expType = Dereference(type2);
7907 if(type2 && type2.kind == classType)
7908 notByReference = true;
7910 else if(exp.op.op == '&' && !exp.op.exp1)
7911 exp.expType = Reference(type2);
7918 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7919 exp.op.exp1.destType = MkClassType("bool");
7920 exp.op.exp1.destType.truth = true;
7921 if(!exp.op.exp1.expType)
7922 ProcessExpressionType(exp.op.exp1);
7924 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7925 FreeType(exp.op.exp1.expType);
7926 exp.op.exp1.expType = MkClassType("bool");
7927 exp.op.exp1.expType.truth = true;
7931 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7932 exp.op.exp2.destType = MkClassType("bool");
7933 exp.op.exp2.destType.truth = true;
7934 if(!exp.op.exp2.expType)
7935 ProcessExpressionType(exp.op.exp2);
7937 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7938 FreeType(exp.op.exp2.expType);
7939 exp.op.exp2.expType = MkClassType("bool");
7940 exp.op.exp2.expType.truth = true;
7943 else if(exp.op.exp1 && exp.op.exp2 &&
7946 ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
7947 (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
7948 ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) &&
7949 (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
7951 if(type1 && type2 &&
7952 // If either both are class or both are not class
7953 ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
7955 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7956 exp.op.exp2.destType = type1;
7958 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7959 exp.op.exp1.destType = type2;
7961 // Warning here for adding Radians + Degrees with no destination type
7962 if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) &&
7963 type1._class.registered && type1._class.registered.type == unitClass &&
7964 type2._class.registered && type2._class.registered.type == unitClass &&
7965 type1._class.registered != type2._class.registered)
7966 Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
7967 type1._class.string, type2._class.string, type1._class.string);
7969 if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
7971 Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7974 Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7976 exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
7977 MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
7980 ProcessExpressionType(exp.op.exp1);
7982 if(type2.kind != pointerType)
7984 ProcessExpressionType(classExp);
7986 exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*',
7987 // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7988 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7990 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
7993 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
7994 MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7995 MkPointer(null, null), null)))),
7996 MkExpMember(classExp, MkIdentifier("typeSize"))))))));
7998 if(!exp.op.exp2.expType)
7999 type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
8001 ProcessExpressionType(exp.op.exp2);
8006 if(!boolResult && ((type1.kind == pointerType || type1.kind == arrayType || (type1.kind == classType && !strcmp(type1._class.string, "String"))) && (type2.kind == intPtrType || type2.kind == int64Type || type2.kind == intType || type2.kind == shortType || type2.kind == charType)))
8008 if(type1.kind != classType && type1.type.kind == voidType)
8009 Compiler_Error($"void *: unknown size\n");
8010 exp.expType = type1;
8011 if(type1) type1.refCount++;
8013 else if(!boolResult && ((type2.kind == pointerType || type2.kind == arrayType || (type2.kind == classType && !strcmp(type2._class.string, "String"))) && (type1.kind == intPtrType || type1.kind == int64Type || type1.kind == intType || type1.kind == shortType || type1.kind == charType)))
8015 if(type2.kind != classType && type2.type.kind == voidType)
8016 Compiler_Error($"void *: unknown size\n");
8017 exp.expType = type2;
8018 if(type2) type2.refCount++;
8020 else if((type1.kind == pointerType && type2.kind != pointerType && type2.kind != arrayType && type2.kind != functionType && type2.kind != methodType && type2.kind != classType && type2.kind != subClassType) ||
8021 (type2.kind == pointerType && type1.kind != pointerType && type1.kind != arrayType && type1.kind != functionType && type1.kind != methodType && type1.kind != classType && type1.kind != subClassType))
8023 Compiler_Warning($"different levels of indirection\n");
8027 bool success = false;
8028 if(type1.kind == pointerType && type2.kind == pointerType)
8030 if(exp.op.op == '+')
8031 Compiler_Error($"cannot add two pointers\n");
8032 else if(exp.op.op == '-')
8034 // Pointer Subtraction gives integer
8035 if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
8044 if(type1.type.kind == templateType)
8046 Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
8049 Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
8051 ProcessExpressionType(classExp);
8053 exp.type = bracketsExp;
8054 exp.list = MkListOne(MkExpOp(
8055 MkExpBrackets(MkListOne(MkExpOp(
8056 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
8058 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/',
8060 //MkExpMember(classExp, MkIdentifier("typeSize"))
8062 // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
8063 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
8065 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
8068 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
8069 MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
8070 MkPointer(null, null), null)))),
8071 MkExpMember(classExp, MkIdentifier("typeSize")))))
8076 ProcessExpressionType(((Expression)exp.list->first).op.exp2);
8085 if(!success && exp.op.exp1.type == constantExp)
8087 // If first expression is constant, try to match that first
8088 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8090 if(exp.expType) FreeType(exp.expType);
8091 exp.expType = exp.op.exp1.destType;
8092 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8095 else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8097 if(exp.expType) FreeType(exp.expType);
8098 exp.expType = exp.op.exp2.destType;
8099 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8105 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8107 if(exp.expType) FreeType(exp.expType);
8108 exp.expType = exp.op.exp2.destType;
8109 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8112 else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8114 if(exp.expType) FreeType(exp.expType);
8115 exp.expType = exp.op.exp1.destType;
8116 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8122 char expString1[10240];
8123 char expString2[10240];
8126 expString1[0] = '\0';
8127 expString2[0] = '\0';
8132 PrintExpression(exp.op.exp1, expString1);
8133 ChangeCh(expString1, '\n', ' ');
8134 PrintExpression(exp.op.exp2, expString2);
8135 ChangeCh(expString2, '\n', ' ');
8136 PrintType(exp.op.exp1.expType, type1, false, true);
8137 PrintType(exp.op.exp2.expType, type2, false, true);
8140 Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
8144 // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
8145 else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8147 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8148 // Convert e.g. / 4 into / 4.0
8149 exp.op.exp1.destType = type2._class.registered.dataType;
8150 if(type2._class.registered.dataType)
8151 type2._class.registered.dataType.refCount++;
8152 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8153 exp.expType = type2;
8154 if(type2) type2.refCount++;
8156 else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8158 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8159 // Convert e.g. / 4 into / 4.0
8160 exp.op.exp2.destType = type1._class.registered.dataType;
8161 if(type1._class.registered.dataType)
8162 type1._class.registered.dataType.refCount++;
8163 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8164 exp.expType = type1;
8165 if(type1) type1.refCount++;
8171 if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8173 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8175 if(!type1._class.registered.dataType)
8176 type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8177 exp.op.exp2.destType = type1._class.registered.dataType;
8178 exp.op.exp2.destType.refCount++;
8180 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8181 type2 = exp.op.exp2.destType;
8183 exp.expType = type2;
8187 if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8189 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8191 if(!type2._class.registered.dataType)
8192 type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8193 exp.op.exp1.destType = type2._class.registered.dataType;
8194 exp.op.exp1.destType.refCount++;
8196 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8197 type1 = exp.op.exp1.destType;
8198 exp.expType = type1;
8202 // TESTING THIS NEW CODE
8203 if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8205 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8207 if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8209 if(exp.expType) FreeType(exp.expType);
8210 exp.expType = exp.op.exp1.expType;
8211 if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8216 else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8218 if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8220 if(exp.expType) FreeType(exp.expType);
8221 exp.expType = exp.op.exp2.expType;
8222 if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8230 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8231 exp.op.exp2.destType = type1;
8235 // Maybe this was meant to be an enum...
8236 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8238 Type oldType = exp.op.exp2.expType;
8239 exp.op.exp2.expType = null;
8240 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8243 exp.op.exp2.expType = oldType;
8248 // TESTING THIS HERE... LATEST ADDITION
8249 if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8251 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8252 exp.op.exp2.destType = type2._class.registered.dataType;
8253 if(type2._class.registered.dataType)
8254 type2._class.registered.dataType.refCount++;
8255 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8257 //exp.expType = type2._class.registered.dataType; //type2;
8258 //if(type2) type2.refCount++;
8261 // TESTING THIS HERE... LATEST ADDITION
8262 if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8264 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8265 exp.op.exp1.destType = type1._class.registered.dataType;
8266 if(type1._class.registered.dataType)
8267 type1._class.registered.dataType.refCount++;
8268 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8269 exp.expType = type1._class.registered.dataType; //type1;
8270 if(type1) type1.refCount++;
8274 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8276 if(exp.expType) FreeType(exp.expType);
8277 exp.expType = exp.op.exp2.destType;
8278 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8280 else if(type1 && type2)
8282 char expString1[10240];
8283 char expString2[10240];
8284 char type1String[1024];
8285 char type2String[1024];
8286 expString1[0] = '\0';
8287 expString2[0] = '\0';
8288 type1String[0] = '\0';
8289 type2String[0] = '\0';
8292 PrintExpression(exp.op.exp1, expString1);
8293 ChangeCh(expString1, '\n', ' ');
8294 PrintExpression(exp.op.exp2, expString2);
8295 ChangeCh(expString2, '\n', ' ');
8296 PrintType(exp.op.exp1.expType, type1String, false, true);
8297 PrintType(exp.op.exp2.expType, type2String, false, true);
8300 Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8302 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8304 exp.expType = exp.op.exp1.expType;
8305 if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8307 else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8309 exp.expType = exp.op.exp2.expType;
8310 if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8317 // Maybe this was meant to be an enum...
8318 if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8320 Type oldType = exp.op.exp1.expType;
8321 exp.op.exp1.expType = null;
8322 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8325 exp.op.exp1.expType = oldType;
8328 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8329 exp.op.exp1.destType = type2;
8332 // TESTING THIS HERE... LATEST ADDITION
8333 if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8335 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8336 exp.op.exp1.destType = type1._class.registered.dataType;
8337 if(type1._class.registered.dataType)
8338 type1._class.registered.dataType.refCount++;
8341 // TESTING THIS HERE... LATEST ADDITION
8342 if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8344 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8345 exp.op.exp2.destType = type2._class.registered.dataType;
8346 if(type2._class.registered.dataType)
8347 type2._class.registered.dataType.refCount++;
8351 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8353 if(exp.expType) FreeType(exp.expType);
8354 exp.expType = exp.op.exp1.destType;
8355 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8359 else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8361 if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8363 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8364 // Convert e.g. / 4 into / 4.0
8365 exp.op.exp1.destType = type2._class.registered.dataType;
8366 if(type2._class.registered.dataType)
8367 type2._class.registered.dataType.refCount++;
8368 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8370 if(exp.op.op == '!')
8372 exp.expType = MkClassType("bool");
8373 exp.expType.truth = true;
8377 exp.expType = type2;
8378 if(type2) type2.refCount++;
8381 else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8383 if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8385 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8386 // Convert e.g. / 4 into / 4.0
8387 exp.op.exp2.destType = type1._class.registered.dataType;
8388 if(type1._class.registered.dataType)
8389 type1._class.registered.dataType.refCount++;
8390 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8392 exp.expType = type1;
8393 if(type1) type1.refCount++;
8398 if(exp.op.exp1 && !exp.op.exp1.expType)
8400 char expString[10000];
8401 expString[0] = '\0';
8404 PrintExpression(exp.op.exp1, expString);
8405 ChangeCh(expString, '\n', ' ');
8408 Compiler_Error($"couldn't determine type of %s\n", expString);
8410 if(exp.op.exp2 && !exp.op.exp2.expType)
8412 char expString[10240];
8413 expString[0] = '\0';
8416 PrintExpression(exp.op.exp2, expString);
8417 ChangeCh(expString, '\n', ' ');
8420 Compiler_Error($"couldn't determine type of %s\n", expString);
8425 FreeType(exp.expType);
8426 exp.expType = MkClassType("bool");
8427 exp.expType.truth = true;
8430 if(exp.op.op != SIZEOF)
8431 exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8432 (!exp.op.exp2 || exp.op.exp2.isConstant);
8434 if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8436 DeclareType(exp.op.exp2.expType, false, false);
8445 case extensionExpressionExp:
8448 exp.isConstant = true;
8449 for(e = exp.list->first; e; e = e.next)
8454 FreeType(e.destType);
8455 e.destType = exp.destType;
8456 if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8458 ProcessExpressionType(e);
8460 exp.destType.count--;
8461 if(!exp.expType && !e.next)
8463 exp.expType = e.expType;
8464 if(e.expType) e.expType.refCount++;
8467 exp.isConstant = false;
8470 // In case a cast became a member...
8471 e = exp.list->first;
8472 if(!e.next && e.type == memberExp)
8474 // Preserve prev, next
8475 Expression next = exp.next, prev = exp.prev;
8478 FreeType(exp.expType);
8479 FreeType(exp.destType);
8489 ProcessExpressionType(exp);
8496 exp.isConstant = true;
8498 ProcessExpressionType(exp.index.exp);
8499 if(!exp.index.exp.isConstant)
8500 exp.isConstant = false;
8502 if(exp.index.exp.expType)
8504 Type source = exp.index.exp.expType;
8505 if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8506 eClass_IsDerived(source._class.registered, containerClass) &&
8507 source._class.registered.templateArgs)
8509 Class _class = source._class.registered;
8510 exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8512 if(exp.index.index && exp.index.index->last)
8514 ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8519 for(e = exp.index.index->first; e; e = e.next)
8521 if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8523 if(e.destType) FreeType(e.destType);
8524 e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8526 ProcessExpressionType(e);
8529 // Check if this type is int
8532 exp.isConstant = false;
8536 exp.expType = Dereference(exp.index.exp.expType);
8538 DeclareType(exp.expType, false, false);
8545 Type methodType = null;
8551 PrintExpression(exp.call.exp, name);
8552 if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8554 //exp.call.exp.expType = null;
8555 PrintExpression(exp.call.exp, name);
8558 if(exp.call.exp.type == identifierExp)
8560 Expression idExp = exp.call.exp;
8561 Identifier id = idExp.identifier;
8562 if(!strcmp(id.string, "__ENDIAN_PAD"))
8564 exp.expType = ProcessTypeString("int", true);
8565 if(exp.call.arguments && exp.call.arguments->first)
8566 ProcessExpressionType(exp.call.arguments->first);
8569 else if(!strcmp(id.string, "Max") ||
8570 !strcmp(id.string, "Min") ||
8571 !strcmp(id.string, "Sgn") ||
8572 !strcmp(id.string, "Abs"))
8574 Expression a = null;
8575 Expression b = null;
8576 Expression tempExp1 = null, tempExp2 = null;
8577 if((!strcmp(id.string, "Max") ||
8578 !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8580 a = exp.call.arguments->first;
8581 b = exp.call.arguments->last;
8585 else if(exp.call.arguments->count == 1)
8587 a = exp.call.arguments->first;
8593 exp.call.arguments->Clear();
8594 idExp.identifier = null;
8596 FreeExpContents(exp);
8598 ProcessExpressionType(a);
8600 ProcessExpressionType(b);
8602 exp.type = bracketsExp;
8603 exp.list = MkList();
8605 if(a.expType && (!b || b.expType))
8607 if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8609 // Use the simpleStruct name/ids for now...
8612 OldList * specs = MkList();
8613 OldList * decls = MkList();
8615 char temp1[1024], temp2[1024];
8617 GetTypeSpecs(a.expType, specs);
8619 if(a && !a.isConstant && a.type != identifierExp)
8621 sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8622 ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8623 tempExp1 = QMkExpId(temp1);
8624 tempExp1.expType = a.expType;
8626 a.expType.refCount++;
8627 ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8629 if(b && !b.isConstant && b.type != identifierExp)
8631 sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8632 ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8633 tempExp2 = QMkExpId(temp2);
8634 tempExp2.expType = b.expType;
8636 b.expType.refCount++;
8637 ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8640 decl = MkDeclaration(specs, decls);
8641 if(!curCompound.compound.declarations)
8642 curCompound.compound.declarations = MkList();
8643 curCompound.compound.declarations->Insert(null, decl);
8648 if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8650 int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8652 MkExpCondition(MkExpBrackets(MkListOne(
8653 MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8654 MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8655 exp.expType = a.expType;
8657 a.expType.refCount++;
8659 else if(!strcmp(id.string, "Abs"))
8662 MkExpCondition(MkExpBrackets(MkListOne(
8663 MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8664 MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8665 exp.expType = a.expType;
8667 a.expType.refCount++;
8669 else if(!strcmp(id.string, "Sgn"))
8671 // ((!(a))?(0):(((a)<0)?(-1):(1)))
8673 MkExpCondition(MkExpBrackets(MkListOne(
8674 MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8675 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8676 MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8677 MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8678 exp.expType = ProcessTypeString("int", false);
8681 FreeExpression(tempExp1);
8682 if(tempExp2) FreeExpression(tempExp2);
8696 if(!exp.call.exp.destType)
8698 exp.call.exp.destType = dummy;
8701 ProcessExpressionType(exp.call.exp);
8702 if(exp.call.exp.destType == dummy)
8705 exp.call.exp.destType = null;
8710 // Check argument types against parameter types
8711 functionType = exp.call.exp.expType;
8713 if(functionType && functionType.kind == TypeKind::methodType)
8715 methodType = functionType;
8716 functionType = methodType.method.dataType;
8718 //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8719 // TOCHECK: Instead of doing this here could this be done per param?
8720 if(exp.call.exp.expType.usedClass)
8722 char typeString[1024];
8723 typeString[0] = '\0';
8724 PrintType(functionType, typeString, true, true);
8725 if(strstr(typeString, "thisclass"))
8727 OldList * specs = MkList();
8730 Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8732 decl = SpecDeclFromString(typeString, specs, null);
8734 // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8735 if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8736 exp.call.exp.expType.usedClass))
8737 thisClassParams = false;
8739 ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8741 Class backupThisClass = thisClass;
8742 thisClass = exp.call.exp.expType.usedClass;
8743 ProcessDeclarator(decl);
8744 thisClass = backupThisClass;
8747 thisClassParams = true;
8749 functionType = ProcessType(specs, decl);
8750 functionType.refCount = 0;
8751 FinishTemplatesContext(context);
8754 FreeList(specs, FreeSpecifier);
8755 FreeDeclarator(decl);
8759 if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8761 Type type = functionType.type;
8762 if(!functionType.refCount)
8764 functionType.type = null;
8765 FreeType(functionType);
8767 //methodType = functionType;
8768 functionType = type;
8770 if(functionType && functionType.kind != TypeKind::functionType)
8772 Compiler_Error($"called object %s is not a function\n", name);
8774 else if(functionType)
8776 bool emptyParams = false, noParams = false;
8777 Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8778 Type type = functionType.params.first;
8779 Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8781 Location oldyylloc = yylloc;
8783 if(!type) emptyParams = true;
8786 if(functionType.extraParam && e)
8788 e.destType = MkClassType(functionType.thisClass.string);
8792 // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8793 if(!functionType.staticMethod)
8795 if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType &&
8796 memberExp.member.exp.expType._class)
8798 type = MkClassType(memberExp.member.exp.expType._class.string);
8803 type = functionType.params.first;
8808 else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8810 type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8815 type = functionType.params.first;
8823 if(type && type.kind == voidType)
8826 if(!type.refCount) FreeType(type);
8830 for( ; e; e = e.next)
8832 if(!type && !emptyParams)
8835 if(methodType && methodType.methodClass)
8836 Compiler_Error($"too many arguments for method %s::%s (%d given, expected %d)\n",
8837 methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8838 noParams ? 0 : functionType.params.count);
8840 Compiler_Error($"too many arguments for function %s (%d given, expected %d)\n",
8841 name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8842 noParams ? 0 : functionType.params.count);
8846 if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8848 Type templatedType = null;
8849 Class _class = methodType.usedClass;
8850 ClassTemplateParameter curParam = null;
8852 if(_class && _class.templateArgs /*&& _class.templateClass*/)
8855 for(sClass = _class; sClass; sClass = sClass.base)
8857 if(sClass.templateClass) sClass = sClass.templateClass;
8859 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8861 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8864 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8866 if(nextClass.templateClass) nextClass = nextClass.templateClass;
8867 id += nextClass.templateParams.count;
8876 if(curParam && _class.templateArgs[id].dataTypeString)
8878 ClassTemplateArgument arg = _class.templateArgs[id];
8880 Context context = SetupTemplatesContext(_class);
8883 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8884 templatedType = ProcessTypeString(arg.dataTypeString, false);
8885 FinishTemplatesContext(context);
8887 e.destType = templatedType;
8890 templatedType.passAsTemplate = true;
8891 // templatedType.refCount++;
8897 if(type) type.refCount++;
8903 if(type) type.refCount++;
8905 // Don't reach the end for the ellipsis
8906 if(type && type.kind != ellipsisType)
8908 Type next = type.next;
8909 if(!type.refCount) FreeType(type);
8914 if(type && type.kind != ellipsisType)
8916 if(methodType && methodType.methodClass)
8917 Compiler_Warning($"not enough arguments for method %s::%s (%d given, expected %d)\n",
8918 methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8919 functionType.params.count + extra);
8921 Compiler_Warning($"not enough arguments for function %s (%d given, expected %d)\n",
8922 name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8923 functionType.params.count + extra);
8926 if(type && !type.refCount) FreeType(type);
8933 kind = TypeKind::functionType;
8936 if(exp.call.exp.type == identifierExp)
8938 char * string = exp.call.exp.identifier.string;
8942 Location oldyylloc = yylloc;
8944 yylloc = exp.call.exp.identifier.loc;
8945 if(strstr(string, "__builtin_") == string);
8947 Compiler_Warning($"%s undefined; assuming extern returning int\n", string);
8948 symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8949 globalContext.symbols.Add((BTNode)symbol);
8950 if(strstr(symbol.string, "::"))
8951 globalContext.hasNameSpace = true;
8956 else if(exp.call.exp.type == memberExp)
8958 /*Compiler_Warning($"%s undefined; assuming returning int\n",
8959 exp.call.exp.member.member.string);*/
8962 Compiler_Warning($"callable object undefined; extern assuming returning int\n");
8964 if(!functionType.returnType)
8966 functionType.returnType = Type
8973 if(functionType && functionType.kind == TypeKind::functionType)
8975 exp.expType = functionType.returnType;
8977 if(functionType.returnType)
8978 functionType.returnType.refCount++;
8980 if(!functionType.refCount)
8981 FreeType(functionType);
8984 if(exp.call.arguments)
8986 for(e = exp.call.arguments->first; e; e = e.next)
8988 Type destType = e.destType;
8989 ProcessExpressionType(e);
8997 Location oldyylloc = yylloc;
8998 bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8999 exp.thisPtr = thisPtr;
9001 // DOING THIS LATER NOW...
9002 if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9004 exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9005 /* TODO: Name Space Fix ups
9006 if(!exp.member.member.classSym)
9007 exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
9011 ProcessExpressionType(exp.member.exp);
9012 if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class &&
9013 exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
9015 exp.isConstant = false;
9018 exp.isConstant = exp.member.exp.isConstant;
9019 type = exp.member.exp.expType;
9023 if(type && (type.kind == templateType))
9025 Class _class = thisClass ? thisClass : currentClass;
9026 ClassTemplateParameter param = null;
9029 for(param = _class.templateParams.first; param; param = param.next)
9031 if(param.type == identifier && exp.member.member && exp.member.member.string && !strcmp(param.name, exp.member.member.string))
9035 if(param && param.defaultArg.member)
9037 Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
9040 Expression expMember = exp.member.exp;
9042 OldList * specs = MkList();
9043 char thisClassTypeString[1024];
9045 FreeIdentifier(exp.member.member);
9047 ProcessExpressionType(argExp);
9050 char * colon = strstr(param.defaultArg.memberString, "::");
9053 char className[1024];
9056 memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
9057 thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
9060 strcpy(thisClassTypeString, _class.fullName);
9063 decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
9065 exp.expType = ProcessType(specs, decl);
9066 if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
9068 Class expClass = exp.expType._class.registered;
9069 Class cClass = null;
9074 char templateString[1024];
9075 ClassTemplateParameter param;
9076 sprintf(templateString, "%s<", expClass.templateClass.fullName);
9077 for(cClass = expClass; cClass; cClass = cClass.base)
9080 for(param = cClass.templateParams.first; param; param = param.next)
9084 ClassTemplateArgument arg;
9085 for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
9086 arg = expClass.templateArgs[id];
9088 for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
9090 ClassTemplateParameter cParam;
9091 //int p = numParams - sClass.templateParams.count;
9094 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
9096 for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
9098 if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
9100 if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9102 arg.dataTypeString = _class.templateArgs[p].dataTypeString;
9103 arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
9115 strcat(argument, arg.name.string);
9116 strcat(argument, " = ");
9122 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9123 char expString[1024];
9124 OldList * specs = MkList();
9125 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9127 char * string = PrintHexUInt64(arg.expression.ui64);
9128 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9130 ProcessExpressionType(exp);
9131 ComputeExpression(exp);
9132 expString[0] = '\0';
9133 PrintExpression(exp, expString);
9134 strcat(argument, expString);
9136 FreeExpression(exp);
9141 strcat(argument, arg.member.name);
9144 case TemplateParameterType::type:
9146 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9148 if(!strcmp(arg.dataTypeString, "thisclass"))
9149 strcat(argument, thisClassTypeString);
9151 strcat(argument, arg.dataTypeString);
9158 if(paramCount) strcat(templateString, ", ");
9159 if(lastParam != p - 1)
9161 strcat(templateString, param.name);
9162 strcat(templateString, " = ");
9164 strcat(templateString, argument);
9173 int len = strlen(templateString);
9174 if(templateString[len-1] == '>') templateString[len++] = ' ';
9175 templateString[len++] = '>';
9176 templateString[len++] = '\0';
9179 Context context = SetupTemplatesContext(_class);
9180 FreeType(exp.expType);
9181 exp.expType = ProcessTypeString(templateString, false);
9182 FinishTemplatesContext(context);
9186 // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9187 exp.type = bracketsExp;
9188 exp.list = MkListOne(MkExpOp(null, '*',
9193 MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9194 MkExpBrackets(MkListOne(
9195 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9197 MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")),
9199 MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9204 else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type &&
9205 (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9207 type = ProcessTemplateParameterType(type.templateParameter);
9211 if(type && (type.kind == templateType));
9212 else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9214 Identifier id = exp.member.member;
9215 TypeKind typeKind = type.kind;
9216 Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9217 if(typeKind == subClassType && exp.member.exp.type == classExp)
9219 _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9220 typeKind = classType;
9223 if(id && (typeKind == intType || typeKind == enumType))
9224 _class = eSystem_FindClass(privateModule, "int");
9229 (exp.member.exp.type == identifierExp &&
9230 !strcmp(exp.member.exp.identifier.string, "this"));*/
9231 Property prop = null;
9232 Method method = null;
9233 DataMember member = null;
9234 Property revConvert = null;
9235 ClassProperty classProp = null;
9237 if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9238 exp.member.memberType = propertyMember;
9240 if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9241 Compiler_Error($"invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9243 if(typeKind != subClassType)
9245 // Prioritize data members over properties for "this"
9246 if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9248 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9249 if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9251 prop = eClass_FindProperty(_class, id.string, privateModule);
9255 if(!member && !prop)
9256 prop = eClass_FindProperty(_class, id.string, privateModule);
9257 if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9258 (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9259 exp.member.thisPtr = true;
9261 // Prioritize properties over data members otherwise
9264 // First look for Public Members (Unless class specifier is provided, which skips public priority)
9267 prop = eClass_FindProperty(_class, id.string, null);
9268 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9269 member = eClass_FindDataMember(_class, id.string, null, null, null);
9272 if(!prop && !member)
9274 method = eClass_FindMethod(_class, id.string, null);
9277 prop = eClass_FindProperty(_class, id.string, privateModule);
9278 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9279 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9285 if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9292 if(!prop && !member)
9293 method = eClass_FindMethod(_class, id.string, privateModule);
9294 if(!prop && !member && !method)
9296 if(typeKind == subClassType)
9298 classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9301 exp.member.memberType = classPropertyMember;
9302 exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9306 // Assume this is a class_data member
9307 char structName[1024];
9308 Identifier id = exp.member.member;
9309 Expression classExp = exp.member.exp;
9312 FreeType(classExp.expType);
9313 classExp.expType = ProcessTypeString("ecere::com::Class", false);
9315 strcpy(structName, "__ecereClassData_");
9316 FullClassNameCat(structName, type._class.string, false);
9317 exp.type = pointerExp;
9318 exp.member.member = id;
9320 exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9321 MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
9322 MkExpBrackets(MkListOne(MkExpOp(
9323 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
9324 MkExpMember(classExp, MkIdentifier("data"))), '+',
9325 MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9330 ProcessExpressionType(exp);
9336 // Check for reverse conversion
9337 // (Convert in an instantiation later, so that we can use
9338 // deep properties system)
9339 Symbol classSym = FindClass(id.string);
9342 Class convertClass = classSym.registered;
9344 revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9351 exp.member.memberType = propertyMember;
9353 ProcessPropertyType(prop);
9354 exp.expType = prop.dataType;
9355 if(prop.dataType) prop.dataType.refCount++;
9359 if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9361 FreeExpContents(exp);
9362 exp.type = identifierExp;
9363 exp.identifier = MkIdentifier("class");
9364 ProcessExpressionType(exp);
9368 exp.member.memberType = dataMember;
9369 DeclareStruct(_class.fullName, false);
9370 if(!member.dataType)
9372 Context context = SetupTemplatesContext(_class);
9373 member.dataType = ProcessTypeString(member.dataTypeString, false);
9374 FinishTemplatesContext(context);
9376 exp.expType = member.dataType;
9377 if(member.dataType) member.dataType.refCount++;
9381 exp.member.memberType = reverseConversionMember;
9382 exp.expType = MkClassType(revConvert._class.fullName);
9390 exp.type = identifierExp;
9391 exp.identifier = exp.member.member;
9394 exp.member.memberType = methodMember;
9396 if(!method.dataType)
9397 ProcessMethodType(method);
9405 // Tricky spot here... To use instance versus class virtual table
9406 // Put it back to what it was... What did we break?
9408 // Had to put it back for overriding Main of Thread global instance
9410 //exp.expType.methodClass = _class;
9411 exp.expType.methodClass = (id && id._class) ? _class : null;
9413 // Need the actual class used for templated classes
9414 exp.expType.usedClass = _class;
9418 if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9420 FreeExpContents(exp);
9421 exp.type = identifierExp;
9422 exp.identifier = MkIdentifier("class");
9423 ProcessExpressionType(exp);
9426 yylloc = exp.member.member.loc;
9427 Compiler_Error($"couldn't find member %s in class %s\n", id.string, _class.fullName);
9429 eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9432 if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9437 while(tClass && !tClass.templateClass) tClass = tClass.base;
9439 if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9442 ClassTemplateParameter curParam = null;
9445 for(sClass = tClass; sClass; sClass = sClass.base)
9448 if(sClass.templateClass) sClass = sClass.templateClass;
9449 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9451 if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9453 for(sClass = sClass.base; sClass; sClass = sClass.base)
9454 id += sClass.templateParams.count;
9462 if(curParam && tClass.templateArgs[id].dataTypeString)
9464 ClassTemplateArgument arg = tClass.templateArgs[id];
9465 Context context = SetupTemplatesContext(tClass);
9467 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9468 FreeType(exp.expType);
9469 exp.expType = ProcessTypeString(arg.dataTypeString, false);
9472 if(exp.expType.kind == thisClassType)
9474 FreeType(exp.expType);
9475 exp.expType = ReplaceThisClassType(_class);
9478 if(tClass.templateClass)
9479 exp.expType.passAsTemplate = true;
9480 //exp.expType.refCount++;
9483 exp.destType = ProcessTypeString(arg.dataTypeString, false);
9484 //exp.destType.refCount++;
9486 if(exp.destType.kind == thisClassType)
9488 FreeType(exp.destType);
9489 exp.destType = ReplaceThisClassType(_class);
9493 FinishTemplatesContext(context);
9496 // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9497 else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9500 ClassTemplateParameter curParam = null;
9503 for(sClass = tClass; sClass; sClass = sClass.base)
9506 if(sClass.templateClass) sClass = sClass.templateClass;
9507 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9509 if(curParam.type == TemplateParameterType::type &&
9510 !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9512 for(sClass = sClass.base; sClass; sClass = sClass.base)
9513 id += sClass.templateParams.count;
9523 ClassTemplateArgument arg = tClass.templateArgs[id];
9524 Context context = SetupTemplatesContext(tClass);
9527 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9529 basicType = ProcessTypeString(arg.dataTypeString, false);
9532 if(basicType.kind == thisClassType)
9534 FreeType(basicType);
9535 basicType = ReplaceThisClassType(_class);
9538 /* DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9539 if(tClass.templateClass)
9540 basicType.passAsTemplate = true;
9543 FreeType(exp.expType);
9545 exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9546 //exp.expType.refCount++;
9549 exp.destType = exp.expType;
9550 exp.destType.refCount++;
9554 Expression newExp { };
9555 OldList * specs = MkList();
9557 decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9559 if(exp.destType) exp.destType.refCount++;
9560 if(exp.expType) exp.expType.refCount++;
9562 exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9563 exp.cast.exp = newExp;
9564 //FreeType(exp.expType);
9565 //exp.expType = null;
9566 //ProcessExpressionType(sourceExp);
9569 FinishTemplatesContext(context);
9572 else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9574 Class expClass = exp.expType._class.registered;
9577 Class cClass = null;
9582 char templateString[1024];
9583 ClassTemplateParameter param;
9584 sprintf(templateString, "%s<", expClass.templateClass.fullName);
9585 while(cClass != expClass)
9588 for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9591 for(param = cClass.templateParams.first; param; param = param.next)
9593 Class cClassCur = null;
9596 ClassTemplateParameter paramCur = null;
9597 ClassTemplateArgument arg;
9598 while(cClassCur != tClass && !paramCur)
9601 for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9602 cClassCur = sClassCur;
9604 for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9606 if(!strcmp(paramCur.name, param.name))
9614 if(paramCur && paramCur.type == TemplateParameterType::type)
9615 arg = tClass.templateArgs[cp];
9617 arg = expClass.templateArgs[p];
9624 strcat(argument, arg.name.string);
9625 strcat(argument, " = ");
9631 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9632 char expString[1024];
9633 OldList * specs = MkList();
9634 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9636 char * string = PrintHexUInt64(arg.expression.ui64);
9637 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9639 ProcessExpressionType(exp);
9640 ComputeExpression(exp);
9641 expString[0] = '\0';
9642 PrintExpression(exp, expString);
9643 strcat(argument, expString);
9645 FreeExpression(exp);
9650 strcat(argument, arg.member.name);
9653 case TemplateParameterType::type:
9655 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9656 strcat(argument, arg.dataTypeString);
9662 if(paramCount) strcat(templateString, ", ");
9663 if(lastParam != p - 1)
9665 strcat(templateString, param.name);
9666 strcat(templateString, " = ");
9668 strcat(templateString, argument);
9677 int len = strlen(templateString);
9678 if(templateString[len-1] == '>') templateString[len++] = ' ';
9679 templateString[len++] = '>';
9680 templateString[len++] = '\0';
9683 FreeType(exp.expType);
9685 Context context = SetupTemplatesContext(tClass);
9686 exp.expType = ProcessTypeString(templateString, false);
9687 FinishTemplatesContext(context);
9694 Compiler_Error($"undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9696 else if(type && (type.kind == structType || type.kind == unionType))
9698 Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9701 exp.expType = memberType;
9703 memberType.refCount++;
9708 char expString[10240];
9709 expString[0] = '\0';
9710 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9711 Compiler_Error($"member operator on non-structure type expression %s\n", expString);
9714 if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9716 if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9718 Identifier id = exp.member.member;
9719 Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9722 FreeType(exp.expType);
9723 exp.expType = ReplaceThisClassType(_class);
9730 // Convert x->y into (*x).y
9733 Type destType = exp.destType;
9735 // DOING THIS LATER NOW...
9736 if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9738 exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9739 /* TODO: Name Space Fix ups
9740 if(!exp.member.member.classSym)
9741 exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9745 exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9746 exp.type = memberExp;
9749 ProcessExpressionType(exp);
9756 //ComputeExpression(exp);
9758 Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9759 if(classSym && classSym.registered)
9761 if(classSym.registered.type == noHeadClass)
9765 DeclareStruct(classSym.string, false);
9766 FreeSpecifier(exp._class);
9767 exp.type = typeSizeExp;
9768 FullClassNameCat(name, classSym.string, false);
9769 exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9773 if(classSym.registered.fixed)
9775 FreeSpecifier(exp._class);
9776 exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9777 exp.type = constantExp;
9781 char className[1024];
9782 strcpy(className, "__ecereClass_");
9783 FullClassNameCat(className, classSym.string, true);
9784 MangleClassName(className);
9786 DeclareClass(classSym, className);
9788 FreeExpContents(exp);
9789 exp.type = pointerExp;
9790 exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9791 exp.member.member = MkIdentifier("structSize");
9801 // exp.isConstant = true;
9806 Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9813 exp.isConstant = true;
9815 DeclareType(type, false, false);
9821 Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9823 FreeType(exp.cast.exp.destType);
9824 exp.cast.exp.destType = type;
9826 ProcessExpressionType(exp.cast.exp);
9831 // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9832 if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9834 void * prev = exp.prev, * next = exp.next;
9835 Type expType = exp.cast.exp.destType;
9836 Expression castExp = exp.cast.exp;
9837 Type destType = exp.destType;
9839 if(expType) expType.refCount++;
9841 //FreeType(exp.destType);
9842 FreeType(exp.expType);
9843 FreeTypeName(exp.cast.typeName);
9846 FreeType(exp.expType);
9847 FreeType(exp.destType);
9849 exp.expType = expType;
9850 exp.destType = destType;
9860 exp.isConstant = exp.cast.exp.isConstant;
9865 case extensionInitializerExp:
9867 Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9870 // We have yet to support this... ( { } initializers are currently processed inside ProcessDeclaration()'s initDeclaration case statement
9871 // ProcessInitializer(exp.initializer.initializer, type);
9877 Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9878 ProcessExpressionType(exp.vaArg.exp);
9886 exp.isConstant = true;
9888 FreeType(exp.cond.cond.destType);
9889 exp.cond.cond.destType = MkClassType("bool");
9890 exp.cond.cond.destType.truth = true;
9891 ProcessExpressionType(exp.cond.cond);
9892 if(!exp.cond.cond.isConstant)
9893 exp.isConstant = false;
9894 for(e = exp.cond.exp->first; e; e = e.next)
9898 FreeType(e.destType);
9899 e.destType = exp.destType;
9900 if(e.destType) e.destType.refCount++;
9902 ProcessExpressionType(e);
9905 exp.expType = e.expType;
9906 if(e.expType) e.expType.refCount++;
9909 exp.isConstant = false;
9912 FreeType(exp.cond.elseExp.destType);
9913 // Added this check if we failed to find an expType
9914 // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9917 exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9919 if(exp.cond.elseExp.destType)
9920 exp.cond.elseExp.destType.refCount++;
9921 ProcessExpressionType(exp.cond.elseExp);
9923 // FIXED THIS: Was done before calling process on elseExp
9924 if(!exp.cond.elseExp.isConstant)
9925 exp.isConstant = false;
9928 case extensionCompoundExp:
9930 if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9932 Statement last = exp.compound.compound.statements->last;
9933 if(last.type == expressionStmt && last.expressions && last.expressions->last)
9935 ((Expression)last.expressions->last).destType = exp.destType;
9937 exp.destType.refCount++;
9939 ProcessStatement(exp.compound);
9940 exp.expType = ((Expression)last.expressions->last).expType;
9941 if(((Expression)last.expressions->last).expType)
9942 exp.expType.refCount++;
9948 Specifier spec = exp._classExp.specifiers->first;
9949 if(spec && spec.type == nameSpecifier)
9951 exp.expType = MkClassType(spec.name);
9952 exp.expType.kind = subClassType;
9953 exp.byReference = true;
9957 exp.expType = MkClassType("ecere::com::Class");
9958 exp.byReference = true;
9964 Class _class = thisClass ? thisClass : currentClass;
9967 Identifier id = exp.classData.id;
9968 char structName[1024];
9969 Expression classExp;
9970 strcpy(structName, "__ecereClassData_");
9971 FullClassNameCat(structName, _class.fullName, false);
9972 exp.type = pointerExp;
9973 exp.member.member = id;
9974 if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9975 classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9977 classExp = MkExpIdentifier(MkIdentifier("class"));
9979 exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9980 MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
9981 MkExpBrackets(MkListOne(MkExpOp(
9982 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
9983 MkExpMember(classExp, MkIdentifier("data"))), '+',
9984 MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9987 ProcessExpressionType(exp);
9995 char * typeString = null;
9996 char typeStringBuf[1024];
9997 if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9998 exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
10000 Class templateClass = exp.destType._class.registered;
10001 typeString = templateClass.templateArgs[2].dataTypeString;
10005 // Guess type from expressions in the array
10007 for(e = exp.list->first; e; e = e.next)
10009 ProcessExpressionType(e);
10012 if(!type) { type = e.expType; type.refCount++; }
10015 // if(!MatchType(e.expType, type, null, null, null, false, false, false))
10016 if(!MatchTypeExpression(e, type, null, false))
10022 e = exp.list->first;
10023 ProcessExpressionType(e);
10026 //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
10027 if(!MatchTypeExpression(e, type, null, false))
10029 FreeType(e.expType);
10040 FreeType(e.expType);
10047 typeStringBuf[0] = '\0';
10048 PrintType(type, typeStringBuf, false, true);
10049 typeString = typeStringBuf;
10057 (Container)& (struct BuiltInContainer)
10059 ._vTbl = class(BuiltInContainer)._vTbl,
10060 ._class = class(BuiltInContainer),
10062 .data = (int[]){ 1, 7, 3, 4, 5 },
10064 .type = class(int),
10067 char templateString[1024];
10068 OldList * initializers = MkList();
10069 OldList * structInitializers = MkList();
10070 OldList * specs = MkList();
10072 Declarator decl = SpecDeclFromString(typeString, specs, null);
10073 sprintf(templateString, "Container<%s>", typeString);
10078 type = ProcessTypeString(typeString, false);
10079 while(e = exp.list->first)
10081 exp.list->Remove(e);
10084 ProcessExpressionType(e);
10085 ListAdd(initializers, MkInitializerAssignment(e));
10091 DeclareStruct("ecere::com::BuiltInContainer", false);
10093 ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/ MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
10094 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10095 ListAdd(structInitializers, /*MkIdentifier("_class")*/ MkInitializerAssignment(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null)));
10096 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10097 ListAdd(structInitializers, /*MkIdentifier("_refCount")*/MkInitializerAssignment(MkExpConstant("0")));
10098 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10099 ListAdd(structInitializers, /*MkIdentifier("data")*/ MkInitializerAssignment(MkExpExtensionInitializer(
10100 MkTypeName(specs, MkDeclaratorArray(decl, null)),
10101 MkInitializerList(initializers))));
10102 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10103 ListAdd(structInitializers, /*MkIdentifier("count")*/ MkInitializerAssignment({ type = constantExp, constant = PrintString(initializers->count) }));
10104 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10105 ListAdd(structInitializers, /*MkIdentifier("type")*/ MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), CopyDeclarator(decl))));
10106 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10107 exp.expType = ProcessTypeString(templateString, false);
10108 exp.type = bracketsExp;
10109 exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
10111 expExt = MkExpExtensionInitializer(MkTypeName(MkListOne(MkSpecifierName("BuiltInContainer")), null),
10112 MkInitializerList(structInitializers)))));
10113 ProcessExpressionType(expExt);
10117 exp.expType = ProcessTypeString("Container", false);
10118 Compiler_Error($"Couldn't determine type of array elements\n");
10124 if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
10126 FreeType(exp.expType);
10127 exp.expType = ReplaceThisClassType(thisClass);
10130 // Resolve structures here
10131 if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
10133 Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
10134 // TODO: Fix members reference...
10137 if(exp.expType.kind != enumType)
10140 String enumName = CopyString(exp.expType.enumName);
10142 // Fixed a memory leak on self-referencing C structs typedefs
10143 // by instantiating a new type rather than simply copying members
10144 // into exp.expType
10145 FreeType(exp.expType);
10146 exp.expType = Type { };
10147 exp.expType.kind = symbol.type.kind;
10148 exp.expType.refCount++;
10149 exp.expType.enumName = enumName;
10151 exp.expType.members = symbol.type.members;
10152 for(member = symbol.type.members.first; member; member = member.next)
10158 for(member = symbol.type.members.first; member; member = member.next)
10160 NamedLink value { name = CopyString(member.name) };
10161 exp.expType.members.Add(value);
10168 if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
10169 else if(exp.destType && !exp.destType.keepCast)
10171 if(!CheckExpressionType(exp, exp.destType, false))
10173 if(!exp.destType.count || unresolved)
10178 if(exp.destType.kind != ellipsisType)
10184 char expString[10240];
10185 expString[0] = '\0';
10187 PrintType(exp.destType, type2, false, true);
10189 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10191 Compiler_Error($"unresolved identifier %s; expected %s\n", expString, type2);
10192 else if(exp.type != dummyExp)
10193 Compiler_Error($"couldn't determine type of %s; expected %s\n", expString, type2);
10198 char expString[10240] ;
10199 expString[0] = '\0';
10200 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10203 Compiler_Error($"unresolved identifier %s\n", expString);
10204 else if(exp.type != dummyExp)
10205 Compiler_Error($"couldn't determine type of %s\n", expString);
10216 PrintType(exp.expType, type1, false, true);
10217 PrintType(exp.destType, type2, false, true);
10220 //CheckExpressionType(exp, exp.destType, false);
10222 if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10223 exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType &&
10224 (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10227 char expString[10240];
10228 expString[0] = '\0';
10229 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10232 CheckExpressionType(exp, exp.destType, false);
10234 // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
10235 if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
10236 Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10238 // TO CHECK: FORCING HERE TO HELP DEBUGGER
10239 FreeType(exp.expType);
10240 exp.destType.refCount++;
10241 exp.expType = exp.destType;
10246 else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10248 Expression newExp { };
10249 char typeString[1024];
10250 OldList * specs = MkList();
10253 typeString[0] = '\0';
10257 if(exp.expType) exp.expType.refCount++;
10258 if(exp.expType) exp.expType.refCount++;
10259 exp.type = castExp;
10260 newExp.destType = exp.expType;
10262 PrintType(exp.expType, typeString, false, false);
10263 decl = SpecDeclFromString(typeString, specs, null);
10265 exp.cast.typeName = MkTypeName(specs, decl);
10266 exp.cast.exp = newExp;
10269 else if(unresolved)
10271 if(exp.identifier._class && exp.identifier._class.name)
10272 Compiler_Error($"unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10273 else if(exp.identifier.string && exp.identifier.string[0])
10274 Compiler_Error($"unresolved identifier %s\n", exp.identifier.string);
10276 else if(!exp.expType && exp.type != dummyExp)
10278 char expString[10240];
10279 expString[0] = '\0';
10280 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10281 Compiler_Error($"couldn't determine type of %s\n", expString);
10284 // Let's try to support any_object & typed_object here:
10285 ApplyAnyObjectLogic(exp);
10287 if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10288 exp.expType._class.registered.type == noHeadClass)
10290 exp.byReference = true;
10292 /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10293 exp.destType._class.registered.type == noHeadClass)
10295 exp.byReference = true;
10297 yylloc = oldyylloc;
10300 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10302 // THIS CODE WILL FIND NEXT MEMBER...
10305 *curMember = (*curMember).next;
10307 if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10309 *curMember = subMemberStack[--(*subMemberStackPos)];
10310 *curMember = (*curMember).next;
10313 // SKIP ALL PROPERTIES HERE...
10314 while((*curMember) && (*curMember).isProperty)
10315 *curMember = (*curMember).next;
10317 if(subMemberStackPos)
10319 while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10321 subMemberStack[(*subMemberStackPos)++] = *curMember;
10323 *curMember = (*curMember).members.first;
10324 while(*curMember && (*curMember).isProperty)
10325 *curMember = (*curMember).next;
10333 if(subMemberStackPos && *subMemberStackPos)
10335 *curMember = subMemberStack[--(*subMemberStackPos)];
10336 *curMember = (*curMember).next;
10340 Class lastCurClass = *curClass;
10342 if(*curClass == _class) break; // REACHED THE END
10344 for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10345 *curMember = (*curClass).membersAndProperties.first;
10348 while((*curMember) && (*curMember).isProperty)
10349 *curMember = (*curMember).next;
10350 if(subMemberStackPos)
10352 while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10354 subMemberStack[(*subMemberStackPos)++] = *curMember;
10356 *curMember = (*curMember).members.first;
10357 while(*curMember && (*curMember).isProperty)
10358 *curMember = (*curMember).next;
10366 static void ProcessInitializer(Initializer init, Type type)
10370 case expInitializer:
10371 if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10373 // TESTING THIS FOR SHUTTING = 0 WARNING
10374 if(init.exp && !init.exp.destType)
10376 FreeType(init.exp.destType);
10377 init.exp.destType = type;
10378 if(type) type.refCount++;
10382 ProcessExpressionType(init.exp);
10383 init.isConstant = init.exp.isConstant;
10389 Expression exp = init.exp;
10390 Instantiation inst = exp.instance;
10391 MembersInit members;
10393 init.type = listInitializer;
10394 init.list = MkList();
10398 for(members = inst.members->first; members; members = members.next)
10400 if(members.type == dataMembersInit)
10403 for(member = members.dataMembers->first; member; member = member.next)
10405 ListAdd(init.list, member.initializer);
10406 member.initializer = null;
10409 // Discard all MembersInitMethod
10412 FreeExpression(exp);
10414 case listInitializer:
10417 Type initializerType = null;
10418 Class curClass = null;
10419 DataMember curMember = null;
10420 DataMember subMemberStack[256];
10421 int subMemberStackPos = 0;
10423 if(type && type.kind == arrayType)
10424 initializerType = Dereference(type);
10425 else if(type && (type.kind == structType || type.kind == unionType))
10426 initializerType = type.members.first;
10428 for(i = init.list->first; i; i = i.next)
10430 if(type && type.kind == classType && type._class && type._class.registered)
10432 // THIS IS FOR A C STYLE INSTANTIATION OF STRUCT CLASSES ONLY... WE ONLY CARE ABOUT DATA MEMBERS, AND ACTUAL MEMORY ORDER (PRIVATE MEMBERS ARE INCLUDED)
10433 FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10434 // TODO: Generate error on initializing a private data member this way from another module...
10437 if(!curMember.dataType)
10438 curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10439 initializerType = curMember.dataType;
10442 ProcessInitializer(i, initializerType);
10443 if(initializerType && type && (type.kind == structType || type.kind == unionType))
10444 initializerType = initializerType.next;
10446 init.isConstant = false;
10449 if(type && type.kind == arrayType)
10450 FreeType(initializerType);
10452 if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10454 Compiler_Error($"Assigning list initializer to non list\n");
10461 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10465 case baseSpecifier:
10467 if(spec.specifier == THISCLASS)
10471 spec.type = nameSpecifier;
10472 spec.name = ReplaceThisClass(thisClass);
10473 spec.symbol = FindClass(spec.name);
10474 ProcessSpecifier(spec, declareStruct);
10479 case nameSpecifier:
10481 Symbol symbol = FindType(curContext, spec.name);
10483 DeclareType(symbol.type, true, true);
10484 else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10485 DeclareStruct(spec.name, false);
10488 case enumSpecifier:
10493 for(e = spec.list->first; e; e = e.next)
10496 ProcessExpressionType(e.exp);
10501 case structSpecifier:
10502 case unionSpecifier:
10504 if(spec.definitions)
10507 Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10509 ProcessClass(spec.definitions, symbol);
10512 for(def = spec.definitions->first; def; def = def.next)
10514 //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10515 ProcessDeclaration(def.decl);
10522 case classSpecifier:
10524 Symbol classSym = FindClass(spec.name);
10525 if(classSym && classSym.registered && classSym.registered.type == structClass)
10526 DeclareStruct(spec.name, false);
10534 static void ProcessDeclarator(Declarator decl)
10538 case identifierDeclarator:
10539 if(decl.identifier.classSym /* TODO: Name Space Fix ups || decl.identifier.nameSpace*/)
10541 FreeSpecifier(decl.identifier._class);
10542 decl.identifier._class = null;
10545 case arrayDeclarator:
10547 ProcessExpressionType(decl.array.exp);
10548 case structDeclarator:
10549 case bracketsDeclarator:
10550 case functionDeclarator:
10551 case pointerDeclarator:
10552 case extendedDeclarator:
10553 case extendedDeclaratorEnd:
10554 if(decl.declarator)
10555 ProcessDeclarator(decl.declarator);
10556 if(decl.type == functionDeclarator)
10558 Identifier id = GetDeclId(decl);
10559 if(id && id._class)
10563 qualifiers = MkListOne(id._class);
10566 if(!decl.function.parameters)
10567 decl.function.parameters = MkList();
10568 decl.function.parameters->Insert(null, param);
10571 if(decl.function.parameters)
10575 for(param = decl.function.parameters->first; param; param = param.next)
10577 if(param.qualifiers && param.qualifiers->first)
10579 Specifier spec = param.qualifiers->first;
10580 if(spec && spec.specifier == TYPED_OBJECT)
10582 Declarator d = param.declarator;
10585 qualifiers = MkListOne(MkSpecifier(VOID));
10586 declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10589 FreeList(param.qualifiers, FreeSpecifier);
10591 param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10592 param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10594 decl.function.parameters->Insert(param, newParam);
10597 else if(spec && spec.specifier == ANY_OBJECT)
10599 Declarator d = param.declarator;
10601 FreeList(param.qualifiers, FreeSpecifier);
10603 param.qualifiers = MkListOne(MkSpecifier(VOID));
10604 param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10606 else if(spec.specifier == THISCLASS)
10610 spec.type = nameSpecifier;
10611 spec.name = ReplaceThisClass(thisClass);
10612 spec.symbol = FindClass(spec.name);
10613 ProcessSpecifier(spec, false);
10618 if(param.declarator)
10619 ProcessDeclarator(param.declarator);
10627 static void ProcessDeclaration(Declaration decl)
10632 case initDeclaration:
10634 bool declareStruct = false;
10636 lineNum = decl.pos.line;
10637 column = decl.pos.col;
10640 if(decl.declarators)
10644 for(d = decl.declarators->first; d; d = d.next)
10646 Type type, subType;
10647 ProcessDeclarator(d.declarator);
10649 type = ProcessType(decl.specifiers, d.declarator);
10653 ProcessInitializer(d.initializer, type);
10655 // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }
10657 if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10658 d.initializer.exp.type == instanceExp)
10660 if(type.kind == classType && type._class ==
10661 d.initializer.exp.expType._class)
10663 Instantiation inst = d.initializer.exp.instance;
10664 inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10666 d.initializer.exp.instance = null;
10667 if(decl.specifiers)
10668 FreeList(decl.specifiers, FreeSpecifier);
10669 FreeList(decl.declarators, FreeInitDeclarator);
10673 decl.type = instDeclaration;
10678 for(subType = type; subType;)
10680 if(subType.kind == classType)
10682 declareStruct = true;
10685 else if(subType.kind == pointerType)
10687 else if(subType.kind == arrayType)
10688 subType = subType.arrayType;
10698 if(decl.specifiers)
10701 for(s = decl.specifiers->first; s; s = s.next)
10703 ProcessSpecifier(s, declareStruct);
10708 case instDeclaration:
10710 ProcessInstantiationType(decl.inst);
10713 case structDeclaration:
10717 bool declareStruct = false;
10719 if(decl.declarators)
10721 for(d = decl.declarators->first; d; d = d.next)
10723 Type type = ProcessType(decl.specifiers, d.declarator);
10725 ProcessDeclarator(d);
10726 for(subType = type; subType;)
10728 if(subType.kind == classType)
10730 declareStruct = true;
10733 else if(subType.kind == pointerType)
10735 else if(subType.kind == arrayType)
10736 subType = subType.arrayType;
10743 if(decl.specifiers)
10745 for(spec = decl.specifiers->first; spec; spec = spec.next)
10746 ProcessSpecifier(spec, declareStruct);
10753 static FunctionDefinition curFunction;
10755 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10757 char propName[1024], propNameM[1024];
10758 char getName[1024], setName[1024];
10761 DeclareProperty(prop, setName, getName);
10763 // eInstance_FireWatchers(object, prop);
10764 strcpy(propName, "__ecereProp_");
10765 FullClassNameCat(propName, prop._class.fullName, false);
10766 strcat(propName, "_");
10767 // strcat(propName, prop.name);
10768 FullClassNameCat(propName, prop.name, true);
10769 MangleClassName(propName);
10771 strcpy(propNameM, "__ecerePropM_");
10772 FullClassNameCat(propNameM, prop._class.fullName, false);
10773 strcat(propNameM, "_");
10774 // strcat(propNameM, prop.name);
10775 FullClassNameCat(propNameM, prop.name, true);
10776 MangleClassName(propNameM);
10778 if(prop.isWatchable)
10781 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10782 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10783 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10786 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10787 ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10788 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10794 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10795 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10796 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10799 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10800 ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10801 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10804 if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) &&
10805 (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10806 curFunction.propSet.fireWatchersDone = true;
10809 static void ProcessStatement(Statement stmt)
10813 lineNum = stmt.pos.line;
10814 column = stmt.pos.col;
10819 ProcessStatement(stmt.labeled.stmt);
10822 // This expression should be constant...
10823 if(stmt.caseStmt.exp)
10825 FreeType(stmt.caseStmt.exp.destType);
10826 stmt.caseStmt.exp.destType = curSwitchType;
10827 if(curSwitchType) curSwitchType.refCount++;
10828 ProcessExpressionType(stmt.caseStmt.exp);
10829 ComputeExpression(stmt.caseStmt.exp);
10831 if(stmt.caseStmt.stmt)
10832 ProcessStatement(stmt.caseStmt.stmt);
10836 if(stmt.compound.context)
10841 Statement prevCompound = curCompound;
10842 Context prevContext = curContext;
10844 if(!stmt.compound.isSwitch)
10846 curCompound = stmt;
10847 curContext = stmt.compound.context;
10850 if(stmt.compound.declarations)
10852 for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10853 ProcessDeclaration(decl);
10855 if(stmt.compound.statements)
10857 for(s = stmt.compound.statements->first; s; s = s.next)
10858 ProcessStatement(s);
10861 curContext = prevContext;
10862 curCompound = prevCompound;
10866 case expressionStmt:
10869 if(stmt.expressions)
10871 for(exp = stmt.expressions->first; exp; exp = exp.next)
10872 ProcessExpressionType(exp);
10880 FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10881 ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10882 ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10883 for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10885 ProcessExpressionType(exp);
10887 if(stmt.ifStmt.stmt)
10888 ProcessStatement(stmt.ifStmt.stmt);
10889 if(stmt.ifStmt.elseStmt)
10890 ProcessStatement(stmt.ifStmt.elseStmt);
10895 Type oldSwitchType = curSwitchType;
10896 if(stmt.switchStmt.exp)
10899 for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10909 e.exp.destType = destType;
10912 ProcessExpressionType(exp);
10915 curSwitchType = exp.expType;
10918 ProcessStatement(stmt.switchStmt.stmt);
10919 curSwitchType = oldSwitchType;
10924 if(stmt.whileStmt.exp)
10928 FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10929 ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10930 ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10931 for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10933 ProcessExpressionType(exp);
10936 if(stmt.whileStmt.stmt)
10937 ProcessStatement(stmt.whileStmt.stmt);
10942 if(stmt.doWhile.exp)
10946 if(stmt.doWhile.exp->last)
10948 FreeType(((Expression)stmt.doWhile.exp->last).destType);
10949 ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10950 ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10952 for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10954 ProcessExpressionType(exp);
10957 if(stmt.doWhile.stmt)
10958 ProcessStatement(stmt.doWhile.stmt);
10964 if(stmt.forStmt.init)
10965 ProcessStatement(stmt.forStmt.init);
10967 if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10969 FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10970 ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10971 ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10974 if(stmt.forStmt.check)
10975 ProcessStatement(stmt.forStmt.check);
10976 if(stmt.forStmt.increment)
10978 for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10979 ProcessExpressionType(exp);
10982 if(stmt.forStmt.stmt)
10983 ProcessStatement(stmt.forStmt.stmt);
10988 Identifier id = stmt.forEachStmt.id;
10989 OldList * exp = stmt.forEachStmt.exp;
10990 OldList * filter = stmt.forEachStmt.filter;
10991 Statement block = stmt.forEachStmt.stmt;
10992 char iteratorType[1024];
10995 bool isBuiltin = exp && exp->last &&
10996 (((Expression)exp->last).type == ExpressionType::arrayExp ||
10997 (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10998 Expression arrayExp;
10999 char * typeString = null;
11000 int builtinCount = 0;
11002 for(e = exp ? exp->first : null; e; e = e.next)
11006 FreeType(e.destType);
11007 e.destType = ProcessTypeString("Container", false);
11009 if(!isBuiltin || e.next)
11010 ProcessExpressionType(e);
11013 source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
11014 if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
11015 eClass_IsDerived(source._class.registered, containerClass)))
11017 Class _class = source ? source._class.registered : null;
11019 Expression expIt = null;
11020 bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
11021 Class arrayClass = eSystem_FindClass(privateModule, "Array");
11022 Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
11023 Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
11024 stmt.type = compoundStmt;
11026 stmt.compound.context = Context { };
11027 stmt.compound.context.parent = curContext;
11028 curContext = stmt.compound.context;
11030 if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
11032 Class mapClass = eSystem_FindClass(privateModule, "Map");
11033 Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
11034 isCustomAVLTree = true;
11035 if(eClass_IsDerived(source._class.registered, avlTreeClass))
11037 else if(eClass_IsDerived(source._class.registered, mapClass))
11040 else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
11041 else if(source && eClass_IsDerived(source._class.registered, linkListClass))
11043 Class listClass = eSystem_FindClass(privateModule, "List");
11045 isList = eClass_IsDerived(source._class.registered, listClass);
11051 OldList * specs = MkList();
11052 decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
11053 MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11054 stmt.compound.declarations = MkListOne(
11055 MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11056 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11057 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")),
11058 MkInitializerAssignment(MkExpBrackets(exp))))));
11063 char typeStringBuf[1024];
11065 // TODO: Merge this code?
11066 arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
11067 if(((Expression)exp->last).type == castExp)
11069 TypeName typeName = ((Expression)exp->last).cast.typeName;
11071 arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
11074 if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
11075 arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
11076 arrayExp.destType._class.registered.templateArgs)
11078 Class templateClass = arrayExp.destType._class.registered;
11079 typeString = templateClass.templateArgs[2].dataTypeString;
11081 else if(arrayExp.list)
11083 // Guess type from expressions in the array
11085 for(e = arrayExp.list->first; e; e = e.next)
11087 ProcessExpressionType(e);
11090 if(!type) { type = e.expType; type.refCount++; }
11093 // if(!MatchType(e.expType, type, null, null, null, false, false, false))
11094 if(!MatchTypeExpression(e, type, null, false))
11100 e = arrayExp.list->first;
11101 ProcessExpressionType(e);
11104 //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
11105 if(!MatchTypeExpression(e, type, null, false))
11107 FreeType(e.expType);
11118 FreeType(e.expType);
11125 typeStringBuf[0] = '\0';
11126 PrintType(type, typeStringBuf, false, true);
11127 typeString = typeStringBuf;
11133 OldList * initializers = MkList();
11135 OldList * specs = MkList();
11140 builtinCount = arrayExp.list->count;
11141 type = ProcessTypeString(typeString, false);
11142 while(e = arrayExp.list->first)
11144 arrayExp.list->Remove(e);
11147 ProcessExpressionType(e);
11148 ListAdd(initializers, MkInitializerAssignment(e));
11151 delete arrayExp.list;
11153 decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
11154 stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier),
11155 MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
11157 ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
11158 /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
11160 FreeList(exp, FreeExpression);
11164 arrayExp.expType = ProcessTypeString("Container", false);
11165 Compiler_Error($"Couldn't determine type of array elements\n");
11170 OldList * specs = MkList();
11172 decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
11173 MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11174 stmt.compound.declarations = MkListOne(
11175 MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11176 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11177 MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))),
11178 MkInitializerAssignment(MkExpBrackets(exp))))));
11181 else if(isLinkList && !isList)
11184 OldList * specs = MkList();
11185 decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11186 stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11187 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11188 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")),
11189 MkInitializerAssignment(MkExpBrackets(exp))))));
11191 /*else if(isCustomAVLTree)
11194 OldList * specs = MkList();
11195 decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11196 stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11197 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11198 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")),
11199 MkInitializerAssignment(MkExpBrackets(exp))))));
11201 else if(_class.templateArgs)
11204 sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11206 sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11208 stmt.compound.declarations = MkListOne(
11209 MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11210 MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null,
11211 MkInitializerAssignment(MkExpBrackets(exp)))))))));
11213 symbol = FindSymbol(id.string, curContext, curContext, false, false);
11215 if(block && block.type == compoundStmt && block.compound.context)
11217 block.compound.context.parent = stmt.compound.context;
11221 block = MkIfStmt(filter, block, null);
11225 stmt.compound.statements = MkListOne(MkForStmt(
11226 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11227 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11228 MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11229 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11231 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11232 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11233 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11238 //OldList * specs = MkList();
11239 // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11241 sprintf(count, "%d", builtinCount);
11243 stmt.compound.statements = MkListOne(MkForStmt(
11244 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11245 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11246 MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11247 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11251 Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11252 stmt.compound.statements = MkListOne(MkForStmt(
11253 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11254 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11255 MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11256 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11259 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11260 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11261 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11263 else if(isLinkList && !isList)
11265 Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11266 Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11267 if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString &&
11268 !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11270 stmt.compound.statements = MkListOne(MkForStmt(
11271 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11272 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11273 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11278 OldList * specs = MkList();
11279 Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11280 stmt.compound.statements = MkListOne(MkForStmt(
11281 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11282 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11283 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11284 MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11285 MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11288 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11289 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11290 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11292 /*else if(isCustomAVLTree)
11294 stmt.compound.statements = MkListOne(MkForStmt(
11295 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11296 MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11297 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11298 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11301 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11302 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11303 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11307 stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11308 MkIdentifier("Next")), null)), block));
11310 ProcessExpressionType(expIt);
11311 if(stmt.compound.declarations->first)
11312 ProcessDeclaration(stmt.compound.declarations->first);
11315 symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11317 ProcessStatement(stmt);
11318 curContext = stmt.compound.context.parent;
11323 Compiler_Error($"Expression is not a container\n");
11336 if(stmt.expressions)
11338 for(exp = stmt.expressions->first; exp; exp = exp.next)
11342 if(curFunction && !curFunction.type)
11343 curFunction.type = ProcessType(
11344 curFunction.specifiers, curFunction.declarator);
11345 FreeType(exp.destType);
11346 exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11347 if(exp.destType) exp.destType.refCount++;
11349 ProcessExpressionType(exp);
11354 case badDeclarationStmt:
11356 ProcessDeclaration(stmt.decl);
11362 if(stmt.asmStmt.inputFields)
11364 for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11365 if(field.expression)
11366 ProcessExpressionType(field.expression);
11368 if(stmt.asmStmt.outputFields)
11370 for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11371 if(field.expression)
11372 ProcessExpressionType(field.expression);
11374 if(stmt.asmStmt.clobberedFields)
11376 for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11378 if(field.expression)
11379 ProcessExpressionType(field.expression);
11386 PropertyWatch propWatch;
11387 OldList * watches = stmt._watch.watches;
11388 Expression object = stmt._watch.object;
11389 Expression watcher = stmt._watch.watcher;
11391 ProcessExpressionType(watcher);
11393 ProcessExpressionType(object);
11397 if(watcher || thisClass)
11399 External external = curExternal;
11400 Context context = curContext;
11402 stmt.type = expressionStmt;
11403 stmt.expressions = MkList();
11405 curExternal = external.prev;
11407 for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11409 ClassFunction func;
11410 char watcherName[1024];
11411 Class watcherClass = watcher ?
11412 ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11413 External createdExternal;
11415 // Create a declaration above
11416 External externalDecl = MkExternalDeclaration(null);
11417 ast->Insert(curExternal.prev, externalDecl);
11419 sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11420 if(propWatch.deleteWatch)
11421 strcat(watcherName, "_delete");
11425 for(propID = propWatch.properties->first; propID; propID = propID.next)
11427 strcat(watcherName, "_");
11428 strcat(watcherName, propID.string);
11432 if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11434 // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11435 func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11436 //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11437 MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11438 ProcessClassFunctionBody(func, propWatch.compound);
11439 propWatch.compound = null;
11441 //afterExternal = afterExternal ? afterExternal : curExternal;
11443 //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11444 createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11446 createdExternal.symbol.idCode = external.symbol.idCode;
11448 curExternal = createdExternal;
11449 ProcessFunction(createdExternal.function);
11452 // Create a declaration above
11454 Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
11455 MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11456 externalDecl.declaration = decl;
11457 if(decl.symbol && !decl.symbol.pointerExternal)
11458 decl.symbol.pointerExternal = externalDecl;
11461 if(propWatch.deleteWatch)
11463 OldList * args = MkList();
11464 ListAdd(args, CopyExpression(object));
11465 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11466 ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11467 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11471 Class _class = object.expType._class.registered;
11474 for(propID = propWatch.properties->first; propID; propID = propID.next)
11476 char propName[1024];
11477 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11480 char getName[1024], setName[1024];
11481 OldList * args = MkList();
11483 DeclareProperty(prop, setName, getName);
11485 // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11486 strcpy(propName, "__ecereProp_");
11487 FullClassNameCat(propName, prop._class.fullName, false);
11488 strcat(propName, "_");
11489 // strcat(propName, prop.name);
11490 FullClassNameCat(propName, prop.name, true);
11492 ListAdd(args, CopyExpression(object));
11493 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11494 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11495 ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11497 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11500 Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11505 Compiler_Error($"Invalid watched object\n");
11508 curExternal = external;
11509 curContext = context;
11512 FreeExpression(watcher);
11514 FreeExpression(object);
11515 FreeList(watches, FreePropertyWatch);
11518 Compiler_Error($"No observer specified and not inside a _class\n");
11522 for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11524 ProcessStatement(propWatch.compound);
11530 case fireWatchersStmt:
11532 OldList * watches = stmt._watch.watches;
11533 Expression object = stmt._watch.object;
11535 // DEBUGGER BUG: Why doesn't watches evaluate to null??
11536 // printf("%X\n", watches);
11537 // printf("%X\n", stmt._watch.watches);
11539 ProcessExpressionType(object);
11544 ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11550 stmt.type = expressionStmt;
11551 stmt.expressions = MkList();
11553 // Check if we're inside a property set
11554 if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11556 watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11560 //Compiler_Error($"No property specified and not inside a property set\n");
11564 for(propID = watches->first; propID; propID = propID.next)
11566 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11569 CreateFireWatcher(prop, object, stmt);
11572 Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
11577 // Fire all properties!
11580 for(base = _class; base; base = base.base)
11582 for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11584 if(prop.isProperty && prop.isWatchable)
11586 CreateFireWatcher(prop, object, stmt);
11593 FreeExpression(object);
11594 FreeList(watches, FreeIdentifier);
11597 Compiler_Error($"Invalid object specified and not inside a class\n");
11601 case stopWatchingStmt:
11603 OldList * watches = stmt._watch.watches;
11604 Expression object = stmt._watch.object;
11605 Expression watcher = stmt._watch.watcher;
11608 ProcessExpressionType(object);
11610 ProcessExpressionType(watcher);
11613 _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11615 if(watcher || thisClass)
11621 stmt.type = expressionStmt;
11622 stmt.expressions = MkList();
11627 // eInstance_StopWatching(object, null, watcher);
11629 ListAdd(args, CopyExpression(object));
11630 ListAdd(args, MkExpConstant("0"));
11631 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11632 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11636 for(propID = watches->first; propID; propID = propID.next)
11638 char propName[1024];
11639 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11642 char getName[1024], setName[1024];
11643 OldList * args = MkList();
11645 DeclareProperty(prop, setName, getName);
11647 // eInstance_StopWatching(object, prop, watcher);
11648 strcpy(propName, "__ecereProp_");
11649 FullClassNameCat(propName, prop._class.fullName, false);
11650 strcat(propName, "_");
11651 // strcat(propName, prop.name);
11652 FullClassNameCat(propName, prop.name, true);
11653 MangleClassName(propName);
11655 ListAdd(args, CopyExpression(object));
11656 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11657 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11658 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11661 Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11666 FreeExpression(object);
11668 FreeExpression(watcher);
11669 FreeList(watches, FreeIdentifier);
11672 Compiler_Error($"Invalid object specified and not inside a class\n");
11675 Compiler_Error($"No observer specified and not inside a class\n");
11682 static void ProcessFunction(FunctionDefinition function)
11684 Identifier id = GetDeclId(function.declarator);
11685 Symbol symbol = function.declarator ? function.declarator.symbol : null;
11686 Type type = symbol ? symbol.type : null;
11687 Class oldThisClass = thisClass;
11688 Context oldTopContext = topContext;
11690 yylloc = function.loc;
11691 // Process thisClass
11693 if(type && type.thisClass)
11695 Symbol classSym = type.thisClass;
11696 Class _class = type.thisClass.registered;
11697 char className[1024];
11698 char structName[1024];
11699 Declarator funcDecl;
11702 bool typedObject = false;
11704 if(_class && !_class.base)
11706 _class = currentClass;
11707 if(_class && !_class.symbol)
11708 _class.symbol = FindClass(_class.fullName);
11709 classSym = _class ? _class.symbol : null;
11710 typedObject = true;
11713 thisClass = _class;
11715 if(inCompiler && _class)
11717 if(type.kind == functionType)
11719 if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11721 //TypeName param = symbol.type.params.first;
11722 Type param = symbol.type.params.first;
11723 symbol.type.params.Remove(param);
11724 //FreeTypeName(param);
11727 if(type.classObjectType != classPointer)
11729 symbol.type.params.Insert(null, MkClassType(_class.fullName));
11730 symbol.type.staticMethod = true;
11731 symbol.type.thisClass = null;
11733 // HIGH DANGER: VERIFYING THIS...
11734 symbol.type.extraParam = false;
11738 strcpy(className, "__ecereClass_");
11739 FullClassNameCat(className, _class.fullName, true);
11741 MangleClassName(className);
11744 FullClassNameCat(structName, _class.fullName, false);
11749 funcDecl = GetFuncDecl(function.declarator);
11752 if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11754 TypeName param = funcDecl.function.parameters->first;
11755 if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11757 funcDecl.function.parameters->Remove(param);
11758 FreeTypeName(param);
11762 // DANGER: Watch for this... Check if it's a Conversion?
11763 // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11765 // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11766 if(!function.propertyNoThis)
11768 TypeName thisParam;
11770 if(type.classObjectType != classPointer)
11772 thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11773 if(!funcDecl.function.parameters)
11774 funcDecl.function.parameters = MkList();
11775 funcDecl.function.parameters->Insert(null, thisParam);
11780 if(type.classObjectType != classPointer)
11782 if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11783 thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11786 thisParam = TypeName
11788 declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11789 qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11791 funcDecl.function.parameters->Insert(null, thisParam);
11796 if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11798 InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11799 funcDecl = GetFuncDecl(initDecl.declarator);
11802 if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11804 TypeName param = funcDecl.function.parameters->first;
11805 if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11807 funcDecl.function.parameters->Remove(param);
11808 FreeTypeName(param);
11812 if(type.classObjectType != classPointer)
11814 // DANGER: Watch for this... Check if it's a Conversion?
11815 if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11817 TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11819 if(!funcDecl.function.parameters)
11820 funcDecl.function.parameters = MkList();
11821 funcDecl.function.parameters->Insert(null, thisParam);
11828 // Add this to the context
11831 if(type.classObjectType != classPointer)
11833 thisSymbol = Symbol
11835 string = CopyString("this");
11836 type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11838 function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11840 if(typedObject && thisSymbol.type)
11842 thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11843 thisSymbol.type.byReference = type.byReference;
11845 thisSymbol = Symbol { string = CopyString("class") };
11846 function.body.compound.context.symbols.Add(thisSymbol);
11852 // Pointer to class data
11854 if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11856 DataMember member = null;
11859 for(base = _class; base && base.type != systemClass; base = base.next)
11861 for(member = base.membersAndProperties.first; member; member = member.next)
11862 if(!member.isProperty)
11868 for(member = _class.membersAndProperties.first; member; member = member.next)
11869 if(!member.isProperty)
11873 char pointerName[1024];
11876 Initializer initializer;
11877 Expression exp, bytePtr;
11879 strcpy(pointerName, "__ecerePointer_");
11880 FullClassNameCat(pointerName, _class.fullName, false);
11882 char className[1024];
11883 strcpy(className, "__ecereClass_");
11884 FullClassNameCat(className, classSym.string, true);
11885 MangleClassName(className);
11888 DeclareClass(classSym, className);
11892 bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11897 sprintf(string, "%d", _class.offset);
11898 exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11902 // ([bytePtr] + [className]->offset)
11903 exp = QBrackets(MkExpOp(bytePtr, '+',
11904 MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11907 // (this ? [exp] : 0)
11908 exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11912 kind = pointerType;
11913 type = Type { refCount = 1, kind = voidType };
11918 yylloc = function.body.loc;
11919 // ([structName] *) [exp]
11920 // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11921 initializer = MkInitializerAssignment(
11922 MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11924 // [structName] * [pointerName] = [initializer];
11925 // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11928 Context prevContext = curContext;
11929 curContext = function.body.compound.context;
11931 decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11932 MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11934 curContext = prevContext;
11938 decl.symbol = null;
11940 if(!function.body.compound.declarations)
11941 function.body.compound.declarations = MkList();
11942 function.body.compound.declarations->Insert(null, decl);
11948 // Loop through the function and replace undeclared identifiers
11949 // which are a member of the class (methods, properties or data)
11950 // by "this.[member]"
11957 FreeSpecifier(id._class);
11960 if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11962 InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11963 id = GetDeclId(initDecl.declarator);
11965 FreeSpecifier(id._class);
11970 topContext = function.body.compound.context;
11972 FunctionDefinition oldFunction = curFunction;
11973 curFunction = function;
11975 ProcessStatement(function.body);
11977 // If this is a property set and no firewatchers has been done yet, add one here
11978 if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11980 Statement prevCompound = curCompound;
11981 Context prevContext = curContext;
11983 Statement fireWatchers = MkFireWatchersStmt(null, null);
11984 if(!function.body.compound.statements) function.body.compound.statements = MkList();
11985 ListAdd(function.body.compound.statements, fireWatchers);
11987 curCompound = function.body;
11988 curContext = function.body.compound.context;
11990 ProcessStatement(fireWatchers);
11992 curContext = prevContext;
11993 curCompound = prevCompound;
11997 curFunction = oldFunction;
12000 if(function.declarator)
12002 ProcessDeclarator(function.declarator);
12005 topContext = oldTopContext;
12006 thisClass = oldThisClass;
12009 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
12010 static void ProcessClass(OldList definitions, Symbol symbol)
12013 External external = curExternal;
12014 Class regClass = symbol ? symbol.registered : null;
12016 // Process all functions
12017 for(def = definitions.first; def; def = def.next)
12019 if(def.type == functionClassDef)
12021 if(def.function.declarator)
12022 curExternal = def.function.declarator.symbol.pointerExternal;
12024 curExternal = external;
12026 ProcessFunction((FunctionDefinition)def.function);
12028 else if(def.type == declarationClassDef)
12030 if(def.decl.type == instDeclaration)
12032 thisClass = regClass;
12033 ProcessInstantiationType(def.decl.inst);
12039 Class backThisClass = thisClass;
12040 if(regClass) thisClass = regClass;
12041 ProcessDeclaration(def.decl);
12042 thisClass = backThisClass;
12045 else if(def.type == defaultPropertiesClassDef && def.defProperties)
12047 MemberInit defProperty;
12049 // Add this to the context
12050 Symbol thisSymbol = Symbol
12052 string = CopyString("this");
12053 type = regClass ? MkClassType(regClass.fullName) : null;
12055 globalContext.symbols.Add((BTNode)thisSymbol);
12057 for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
12059 thisClass = regClass;
12060 ProcessMemberInitData(defProperty, regClass, null, null, null, null);
12064 globalContext.symbols.Remove((BTNode)thisSymbol);
12065 FreeSymbol(thisSymbol);
12067 else if(def.type == propertyClassDef && def.propertyDef)
12069 PropertyDef prop = def.propertyDef;
12071 // Add this to the context
12073 Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
12074 globalContext.symbols.Add(thisSymbol);
12077 thisClass = regClass;
12084 string = CopyString("this");
12085 type = MkClassType(regClass.fullName);
12087 prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12090 curExternal = prop.symbol ? prop.symbol.externalSet : null;
12091 ProcessStatement(prop.setStmt);
12099 string = CopyString("this");
12100 type = MkClassType(regClass.fullName);
12102 prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12105 curExternal = prop.symbol ? prop.symbol.externalGet : null;
12106 ProcessStatement(prop.getStmt);
12114 string = CopyString("this");
12115 type = MkClassType(regClass.fullName);
12117 prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12120 curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
12121 ProcessStatement(prop.issetStmt);
12127 globalContext.symbols.Remove(thisSymbol);
12128 FreeSymbol(thisSymbol);
12131 else if(def.type == propertyWatchClassDef && def.propertyWatch)
12133 PropertyWatch propertyWatch = def.propertyWatch;
12135 thisClass = regClass;
12136 if(propertyWatch.compound)
12140 string = CopyString("this");
12141 type = regClass ? MkClassType(regClass.fullName) : null;
12144 propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
12146 curExternal = null;
12147 ProcessStatement(propertyWatch.compound);
12154 void ComputeDataTypes()
12158 currentClass = null;
12160 containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
12162 temp.symbol = Symbol { id = -1000, idCode = -1000 };
12164 // WHERE SHOULD THIS GO?
12165 // curExternal = ast->first;
12166 ast->Insert(null, temp);
12168 curExternal = temp;
12170 DeclareStruct("ecere::com::Class", false);
12171 DeclareStruct("ecere::com::Instance", false);
12172 DeclareStruct("ecere::com::Property", false);
12173 DeclareStruct("ecere::com::DataMember", false);
12174 DeclareStruct("ecere::com::Method", false);
12175 DeclareStruct("ecere::com::SerialBuffer", false);
12176 DeclareStruct("ecere::com::ClassTemplateArgument", false);
12180 for(external = ast->first; external; external = external.next)
12182 afterExternal = curExternal = external;
12183 if(external.type == functionExternal)
12185 currentClass = external.function._class;
12186 ProcessFunction(external.function);
12188 // There shouldn't be any _class member access here anyways...
12189 else if(external.type == declarationExternal)
12191 currentClass = null;
12192 ProcessDeclaration(external.declaration);
12194 else if(external.type == classExternal)
12196 ClassDefinition _class = external._class;
12197 currentClass = external.symbol.registered;
12198 if(_class.definitions)
12200 ProcessClass(_class.definitions, _class.symbol);
12204 // Free class data...
12205 ast->Remove(external);
12209 else if(external.type == nameSpaceExternal)
12211 thisNameSpace = external.id.string;
12214 currentClass = null;
12215 thisNameSpace = null;
12217 delete temp.symbol;