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 Type ProcessTemplateParameterType(TemplateParameter param)
63 if(param && param.type == TemplateParameterType::type && (param.dataType || param.dataTypeString))
65 // TOFIX: Will need to free this Type
68 if(param.dataTypeString)
69 param.baseType = ProcessTypeString(param.dataTypeString, false);
71 param.baseType = ProcessType(param.dataType.specifiers, param.dataType.decl);
73 return param.baseType;
78 bool NeedCast(Type type1, Type type2)
80 if(!type1 || !type2 || type1.keepCast || type2.keepCast) return true;
82 if(type1.kind == templateType && type2.kind == int64Type && type2.passAsTemplate == false)
87 if(type1.kind == type2.kind)
96 if(type1.passAsTemplate && !type2.passAsTemplate)
98 return type1.isSigned != type2.isSigned;
100 return type1._class != type2._class;
102 return NeedCast(type1.type, type2.type);
104 return true; //false; ????
110 static void ReplaceClassMembers(Expression exp, Class _class)
112 if(exp.type == identifierExp && exp.identifier)
114 Identifier id = exp.identifier;
116 Symbol symbol = null;
117 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
119 // First, check if the identifier is declared inside the function
120 for(ctx = curContext; ctx != topContext.parent && !symbol; ctx = ctx.parent)
122 symbol = (Symbol)ctx.symbols.FindString(id.string);
127 // If it is not, check if it is a member of the _class
128 if(!symbol && ((!id._class || (id._class.name && !strcmp(id._class.name, "property"))) || (id.classSym && eClass_IsDerived(_class, id.classSym.registered))))
130 Property prop = eClass_FindProperty(_class, id.string, privateModule);
131 Method method = null;
132 DataMember member = null;
133 ClassProperty classProp = null;
136 method = eClass_FindMethod(_class, id.string, privateModule);
139 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
140 if(!prop && !method && !member)
142 classProp = eClass_FindClassProperty(_class, id.string);
144 if(prop || method || member || classProp)
146 // Replace by this.[member]
147 exp.type = memberExp;
148 exp.member.member = id;
149 exp.member.memberType = unresolvedMember;
150 exp.member.exp = QMkExpId("this");
151 //exp.member.exp.loc = exp.loc;
152 exp.addedThis = true;
154 else if(_class && _class.templateParams.first)
157 for(sClass = _class; sClass; sClass = sClass.base)
159 if(sClass.templateParams.first)
161 ClassTemplateParameter param;
162 for(param = sClass.templateParams.first; param; param = param.next)
164 if(param.type == expression && !strcmp(param.name, id.string))
166 Expression argExp = GetTemplateArgExpByName(param.name, _class, TemplateParameterType::expression);
171 OldList * specs = MkList();
173 FreeIdentifier(exp.member.member);
175 ProcessExpressionType(argExp);
177 decl = SpecDeclFromString(param.dataTypeString, specs, null);
179 exp.expType = ProcessType(specs, decl);
181 // *[expType] *[argExp]
182 exp.type = bracketsExp;
183 exp.list = MkListOne(MkExpOp(null, '*',
184 MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpOp(null, '&', argExp))));
195 ////////////////////////////////////////////////////////////////////////
196 // PRINTING ////////////////////////////////////////////////////////////
197 ////////////////////////////////////////////////////////////////////////
199 public char * PrintInt(int64 result)
202 if(result > MAXINT64)
203 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
205 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
206 return CopyString(temp);
209 public char * PrintUInt(uint64 result)
212 if(result > MAXDWORD)
213 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
214 else if(result > MAXINT)
215 sprintf(temp, FORMAT64HEX /*"0x%I64X"*/, result);
217 sprintf(temp, FORMAT64D /*"%I64d"*/, result);
218 return CopyString(temp);
221 public char * PrintInt64(int64 result)
224 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
225 return CopyString(temp);
228 public char * PrintUInt64(uint64 result)
231 if(result > MAXINT64)
232 sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
234 sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
235 return CopyString(temp);
238 public char * PrintHexUInt(uint64 result)
241 if(result > MAXDWORD)
242 sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
244 sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
245 return CopyString(temp);
248 public char * PrintHexUInt64(uint64 result)
251 if(result > MAXDWORD)
252 sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
254 sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
255 return CopyString(temp);
258 public char * PrintShort(short result)
261 sprintf(temp, "%d", (unsigned short)result);
262 return CopyString(temp);
265 public char * PrintUShort(unsigned short result)
269 sprintf(temp, "0x%X", (int)result);
271 sprintf(temp, "%d", result);
272 return CopyString(temp);
275 public char * PrintChar(char result)
278 if(result > 0 && isprint(result))
279 sprintf(temp, "'%c'", result);
281 sprintf(temp, "%d", result);
283 //sprintf(temp, "%#X", result);
284 sprintf(temp, "0x%X", (unsigned char)result);
285 return CopyString(temp);
288 public char * PrintUChar(unsigned char result)
291 sprintf(temp, "0x%X", result);
292 return CopyString(temp);
295 public char * PrintFloat(float result)
298 sprintf(temp, "%.16ff", result);
299 return CopyString(temp);
302 public char * PrintDouble(double result)
305 sprintf(temp, "%.16f", result);
306 return CopyString(temp);
309 ////////////////////////////////////////////////////////////////////////
310 ////////////////////////////////////////////////////////////////////////
312 //public Operand GetOperand(Expression exp);
314 #define GETVALUE(name, t) \
315 public bool Get##name(Expression exp, t * value2) \
317 Operand op2 = GetOperand(exp); \
318 if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
319 else if(op2.kind == intType) *value2 = (t) op2.ui; \
320 if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
321 else if(op2.kind == int64Type) *value2 = (t) op2.ui64; \
322 else if(op2.kind == intPtrType && op2.type.isSigned) *value2 = (t) op2.i64; \
323 else if(op2.kind == intPtrType) *value2 = (t) op2.ui64; \
324 else if(op2.kind == shortType && op2.type.isSigned) *value2 = (t) op2.s; \
325 else if(op2.kind == shortType) *value2 = (t) op2.us; \
326 else if(op2.kind == charType && op2.type.isSigned) *value2 = (t) op2.c; \
327 else if(op2.kind == charType) *value2 = (t) op2.uc; \
328 else if(op2.kind == floatType) *value2 = (t) op2.f; \
329 else if(op2.kind == doubleType) *value2 = (t) op2.d; \
330 else if(op2.kind == pointerType) *value2 = (t) op2.ui64; \
337 GETVALUE(UInt, unsigned int);
338 GETVALUE(Int64, int64);
339 GETVALUE(UInt64, uint64);
340 GETVALUE(IntPtr, intptr);
341 GETVALUE(UIntPtr, uintptr);
342 GETVALUE(Short, short);
343 GETVALUE(UShort, unsigned short);
344 GETVALUE(Char, char);
345 GETVALUE(UChar, unsigned char);
346 GETVALUE(Float, float);
347 GETVALUE(Double, double);
349 void ComputeExpression(Expression exp);
351 void ComputeClassMembers(Class _class, bool isMember)
353 DataMember member = isMember ? (DataMember) _class : null;
354 Context context = isMember ? null : SetupTemplatesContext(_class);
355 if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) &&
356 (_class.type == bitClass || (!_class.structSize || _class.structSize == _class.offset)) && _class.computeSize))
359 int unionMemberOffset = 0;
362 if(!member && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass) && _class.memberOffset && _class.memberOffset > _class.base.structSize)
363 _class.memberOffset = (_class.base && _class.base.type != systemClass) ? _class.base.structSize : 0;
365 if(!member && _class.destructionWatchOffset)
366 _class.memberOffset += sizeof(OldList);
368 // To avoid reentrancy...
369 //_class.structSize = -1;
372 DataMember dataMember;
373 for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
375 if(!dataMember.isProperty)
377 if(dataMember.type == normalMember && dataMember.dataTypeString && !dataMember.dataType)
379 /*if(dataMember.dataType)
381 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
382 /*if(!dataMember.dataType)
383 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
391 DataMember dataMember;
392 for(dataMember = member ? member.members.first : _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
394 if(!dataMember.isProperty && (dataMember.type != normalMember || dataMember.dataTypeString))
396 if(!isMember && _class.type == bitClass && dataMember.dataType)
398 BitMember bitMember = (BitMember) dataMember;
402 ComputeTypeSize(dataMember.dataType);
404 if(bitMember.pos == -1) bitMember.pos = _class.memberOffset;
405 if(!bitMember.size) bitMember.size = dataMember.dataType.size * 8;
407 _class.memberOffset = bitMember.pos + bitMember.size;
408 for(d = 0; d<bitMember.size; d++)
414 bitMember.mask = mask << bitMember.pos;
416 else if(dataMember.type == normalMember && dataMember.dataType)
421 // Prevent infinite recursion
422 if(dataMember.dataType.kind != classType ||
423 ((!dataMember.dataType._class || !dataMember.dataType._class.registered || dataMember.dataType._class.registered != _class ||
424 _class.type != structClass)))
425 ComputeTypeSize(dataMember.dataType);
427 if(dataMember.dataType.bitFieldCount)
429 bitFields += dataMember.dataType.bitFieldCount;
436 int size = (bitFields + 7) / 8;
440 // TESTING THIS PADDING CODE
443 member.structAlignment = Max(member.structAlignment, alignment);
445 if(member.memberOffset % alignment)
446 member.memberOffset += alignment - (member.memberOffset % alignment);
449 dataMember.offset = member.memberOffset;
450 if(member.type == unionMember)
451 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
454 member.memberOffset += size;
459 // TESTING THIS PADDING CODE
462 _class.structAlignment = Max(_class.structAlignment, alignment);
464 if(_class.memberOffset % alignment)
465 _class.memberOffset += alignment - (_class.memberOffset % alignment);
468 dataMember.offset = _class.memberOffset;
469 _class.memberOffset += size;
473 size = dataMember.dataType.size;
474 alignment = dataMember.dataType.alignment;
485 // TESTING THIS PADDING CODE
488 member.structAlignment = Max(member.structAlignment, alignment);
490 if(member.memberOffset % alignment)
491 member.memberOffset += alignment - (member.memberOffset % alignment);
494 dataMember.offset = member.memberOffset;
495 if(member.type == unionMember)
496 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
499 member.memberOffset += size;
504 // TESTING THIS PADDING CODE
507 _class.structAlignment = Max(_class.structAlignment, alignment);
509 if(_class.memberOffset % alignment)
510 _class.memberOffset += alignment - (_class.memberOffset % alignment);
513 dataMember.offset = _class.memberOffset;
514 _class.memberOffset += size;
519 ComputeClassMembers((Class)dataMember, true);
523 // THERE WASN'T A MAX HERE ? member.structAlignment = dataMember.structAlignment;
524 member.structAlignment = Max(member.structAlignment, dataMember.structAlignment);
525 dataMember.offset = member.memberOffset;
526 if(member.type == unionMember)
527 unionMemberOffset = Max(unionMemberOffset, dataMember.memberOffset);
529 member.memberOffset += dataMember.memberOffset;
533 _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
534 dataMember.offset = _class.memberOffset;
535 _class.memberOffset += dataMember.memberOffset;
543 int size = (bitFields + 7) / 8;
547 // TESTING THIS PADDING CODE
550 member.structAlignment = Max(member.structAlignment, alignment);
552 if(member.memberOffset % alignment)
553 member.memberOffset += alignment - (member.memberOffset % alignment);
556 if(member.type == unionMember)
557 unionMemberOffset = Max(unionMemberOffset, dataMember.dataType.size);
560 member.memberOffset += size;
565 // TESTING THIS PADDING CODE
568 _class.structAlignment = Max(_class.structAlignment, alignment);
570 if(_class.memberOffset % alignment)
571 _class.memberOffset += alignment - (_class.memberOffset % alignment);
573 _class.memberOffset += size;
578 if(member && member.type == unionMember)
580 member.memberOffset = unionMemberOffset;
585 /*if(_class.type == structClass)
586 _class.size = _class.memberOffset;
590 if(_class.type != bitClass)
593 if(_class.structAlignment)
595 if(_class.memberOffset % _class.structAlignment)
596 extra += _class.structAlignment - (_class.memberOffset % _class.structAlignment);
598 _class.structSize = (_class.base ? (_class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize) : 0) + _class.memberOffset + extra;
602 for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
604 if(prop.isProperty && prop.isWatchable)
606 prop.watcherOffset = _class.structSize;
607 _class.structSize += sizeof(OldList);
615 for(derivative = _class.derivatives.first; derivative; derivative = derivative.next)
617 Class deriv = derivative.data;
619 if(deriv.computeSize)
621 // TESTING THIS NEW CODE HERE... TRYING TO FIX ScrollBar MEMBERS DEBUGGING
622 deriv.offset = /*_class.offset + */_class.structSize;
623 deriv.memberOffset = 0;
624 // ----------------------
626 deriv.structSize = deriv.offset;
628 ComputeClassMembers(deriv, false);
636 FinishTemplatesContext(context);
639 public void ComputeModuleClasses(Module module)
644 for(subModule = module.modules.first; subModule; subModule = subModule.next)
645 ComputeModuleClasses(subModule.data);
646 for(_class = module.classes.first; _class; _class = _class.next)
647 ComputeClassMembers(_class, false);
651 public int ComputeTypeSize(Type type)
653 uint size = type ? type.size : 0;
654 if(!size && type && !type.computing)
656 type.computing = true;
659 case charType: type.alignment = size = sizeof(char); break;
660 case intType: type.alignment = size = sizeof(int); break;
661 case int64Type: type.alignment = size = sizeof(int64); break;
662 case intPtrType: type.alignment = size = targetBits / 8; break;
663 case longType: type.alignment = size = sizeof(long); break;
664 case shortType: type.alignment = size = sizeof(short); break;
665 case floatType: type.alignment = size = sizeof(float); break;
666 case doubleType: type.alignment = size = sizeof(double); break;
669 Class _class = type._class ? type._class.registered : null;
671 if(_class && _class.type == structClass)
673 // Ensure all members are properly registered
674 ComputeClassMembers(_class, false);
675 type.alignment = _class.structAlignment;
676 size = _class.structSize;
677 if(type.alignment && size % type.alignment)
678 size += type.alignment - (size % type.alignment);
681 else if(_class && (_class.type == unitClass ||
682 _class.type == enumClass ||
683 _class.type == bitClass))
686 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
687 size = type.alignment = ComputeTypeSize(_class.dataType);
690 size = type.alignment = targetBits / 8; // sizeof(Instance *);
693 case pointerType: case subClassType: size = type.alignment = targetBits / 8; /*sizeof(void *); */break;
695 if(type.arraySizeExp)
697 ProcessExpressionType(type.arraySizeExp);
698 ComputeExpression(type.arraySizeExp);
699 if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType &&
700 (type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
702 Location oldLoc = yylloc;
703 // bool isConstant = type.arraySizeExp.isConstant;
704 char expression[10240];
705 expression[0] = '\0';
706 type.arraySizeExp.expType = null;
707 yylloc = type.arraySizeExp.loc;
709 PrintExpression(type.arraySizeExp, expression);
710 Compiler_Error($"Array size not constant int (%s)\n", expression);
713 GetInt(type.arraySizeExp, &type.arraySize);
721 else if(type.enumClass)
723 if(type.enumClass && type.enumClass.registered && type.enumClass.registered.type == enumClass)
725 type.arraySize = (int)eClass_GetProperty(type.enumClass.registered, "enumSize");
732 // Unimplemented auto size
736 size = ComputeTypeSize(type.type) * type.arraySize;
737 type.alignment = type.type.alignment;
743 for(member = type.members.first; member; member = member.next)
745 uint addSize = ComputeTypeSize(member);
747 member.offset = size;
748 if(member.alignment && size % member.alignment)
749 member.offset += member.alignment - (size % member.alignment);
750 size = member.offset;
752 type.alignment = Max(type.alignment, member.alignment);
755 if(type.alignment && size % type.alignment)
756 size += type.alignment - (size % type.alignment);
762 for(member = type.members.first; member; member = member.next)
764 uint addSize = ComputeTypeSize(member);
766 member.offset = size;
767 if(member.alignment && size % member.alignment)
768 member.offset += member.alignment - (size % member.alignment);
769 size = member.offset;
771 type.alignment = Max(type.alignment, member.alignment);
772 size = Max(size, addSize);
774 if(type.alignment && size % type.alignment)
775 size += type.alignment - (size % type.alignment);
780 TemplateParameter param = type.templateParameter;
781 Type baseType = ProcessTemplateParameterType(param);
783 size = ComputeTypeSize(baseType);
785 size = sizeof(uint64);
790 size = sizeof(enum { test });
795 size = targetBits / 8; //sizeof(void *);
800 type.computing = false;
806 /*static */int AddMembers(OldList * declarations, Class _class, bool isMember, uint * retSize, Class topClass)
808 // This function is in need of a major review when implementing private members etc.
809 DataMember topMember = isMember ? (DataMember) _class : null;
814 Context context = isMember ? null : SetupTemplatesContext(_class);
816 if(!isMember && _class.base)
818 maxSize = _class.structSize;
819 //if(_class.base.type != systemClass) // Commented out with new Instance _class
821 // DANGER: Testing this noHeadClass here...
822 if(_class.type == structClass || _class.type == noHeadClass)
823 /*totalSize = */AddMembers(declarations, _class.base, false, &totalSize, topClass);
825 maxSize -= _class.base.templateClass ? _class.base.templateClass.structSize : _class.base.structSize;
829 for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
831 if(!member.isProperty)
837 if(member.dataTypeString)
839 OldList * specs = MkList(), * decls = MkList();
842 decl = SpecDeclFromString(member.dataTypeString, specs,
843 MkDeclaratorIdentifier(MkIdentifier(member.name)));
844 ListAdd(decls, MkStructDeclarator(decl, null));
845 ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, decls, null)));
848 member.dataType = ProcessType(specs, decl);
850 ReplaceThisClassSpecifiers(specs, topClass /*member._class*/);
853 Type type = ProcessType(specs, decl);
854 DeclareType(member.dataType, false, false);
858 if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
859 member.dataType._class.registered && member.dataType._class.registered.type == structClass)
860 DeclareStruct(member.dataType._class.string, false);
863 ComputeTypeSize(member.dataType);
864 size = member.dataType.size;
865 alignment = member.dataType.alignment;
869 if(totalSize % alignment)
870 totalSize += alignment - (totalSize % alignment);
879 OldList * specs = MkList(), * list = MkList();
882 AddMembers(list, (Class)member, true, &size, topClass);
884 MkStructOrUnion((member.type == unionMember)?unionSpecifier:structSpecifier, null, list));
885 ListAdd(declarations, MkClassDefDeclaration(MkStructDeclaration(specs, null, null)));
886 alignment = member.structAlignment;
890 if(totalSize % alignment)
891 totalSize += alignment - (totalSize % alignment);
901 if(topMember && topMember.type == unionMember)
902 *retSize = Max(*retSize, totalSize);
904 *retSize += totalSize;
906 else if(totalSize < maxSize && _class.type != systemClass)
909 if(!isMember && _class.structAlignment && totalSize % _class.structAlignment)
910 autoPadding = _class.structAlignment - (totalSize % _class.structAlignment);
911 if(totalSize + autoPadding < maxSize)
914 sprintf(sizeString, "%d", maxSize - totalSize);
915 ListAdd(declarations,
916 MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(CHAR)),
917 MkListOne(MkDeclaratorArray(MkDeclaratorIdentifier(MkIdentifier("__ecere_padding")), MkExpConstant(sizeString))), null)));
921 FinishTemplatesContext(context);
922 return topMember ? topMember.memberID : _class.memberID;
925 static int DeclareMembers(Class _class, bool isMember)
927 DataMember topMember = isMember ? (DataMember) _class : null;
930 Context context = isMember ? null : SetupTemplatesContext(_class);
932 if(!isMember && (_class.type == structClass || _class.type == noHeadClass) && _class.base.type != systemClass)
933 DeclareMembers(_class.base, false);
935 for(member = isMember ? topMember.members.first : _class.membersAndProperties.first; member; member = member.next)
937 if(!member.isProperty)
944 if(member.dataType && member.dataType.kind == classType && member.dataType._class &&
945 member.dataType._class.registered && member.dataType._class.registered.type == structClass)
946 DeclareStruct(member.dataType._class.string, false);
948 if(!member.dataType && member.dataTypeString)
949 member.dataType = ProcessTypeString(member.dataTypeString, false);
951 DeclareType(member.dataType, false, false);
957 DeclareMembers((Class)member, true);
964 FinishTemplatesContext(context);
966 return topMember ? topMember.memberID : _class.memberID;
969 void DeclareStruct(char * name, bool skipNoHead)
971 External external = null;
972 Symbol classSym = FindClass(name);
974 if(!inCompiler || !classSym) return;
976 // We don't need any declaration for bit classes...
977 if(classSym.registered &&
978 (classSym.registered.type == bitClass || classSym.registered.type == unitClass || classSym.registered.type == enumClass))
981 /*if(classSym.registered.templateClass)
982 return DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
985 if(classSym.registered && classSym.imported && !classSym.declaredStructSym)
987 // Add typedef struct
989 OldList * specifiers, * declarators;
990 OldList * declarations = null;
991 char structName[1024];
992 external = (classSym.registered && classSym.registered.type == structClass) ?
993 classSym.pointerExternal : classSym.structExternal;
995 // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
996 // Moved this one up because DeclareClass done later will need it
998 classSym.declaring++;
1000 if(strchr(classSym.string, '<'))
1002 if(classSym.registered.templateClass)
1004 DeclareStruct(classSym.registered.templateClass.fullName, skipNoHead);
1005 classSym.declaring--;
1011 DeclareMembers(classSym.registered, false);
1014 FullClassNameCat(structName, name, false);
1017 external = MkExternalDeclaration(null);*/
1021 classSym.declaredStructSym = true;
1023 declarations = MkList();
1025 AddMembers(declarations, classSym.registered, false, null, classSym.registered);
1027 //ListAdd(specifiers, MkSpecifier(TYPEDEF));
1028 //ListAdd(specifiers, MkStructOrUnion(structSpecifier, null, declarations));
1030 if(!declarations->count)
1032 FreeList(declarations, null);
1033 declarations = null;
1036 if(skipNoHead || declarations)
1038 if(external && external.declaration)
1040 ((Specifier)external.declaration.specifiers->first).definitions = declarations;
1042 if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1045 //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1048 if(classSym.structExternal)
1049 ast->Move(classSym.structExternal, curExternal.prev);
1050 ast->Move(classSym.pointerExternal, curExternal.prev);
1052 classSym.id = curExternal.symbol.idCode;
1053 classSym.idCode = curExternal.symbol.idCode;
1054 // external = classSym.pointerExternal;
1055 //external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1061 external = MkExternalDeclaration(null);
1063 specifiers = MkList();
1064 declarators = MkList();
1065 ListAdd(specifiers, MkStructOrUnion(structSpecifier, MkIdentifier(structName), declarations));
1068 d = MkDeclaratorIdentifier(MkIdentifier(structName));
1069 ListAdd(declarators, MkInitDeclarator(d, null));
1071 external.declaration = decl = MkDeclaration(specifiers, declarators);
1072 if(decl.symbol && !decl.symbol.pointerExternal)
1073 decl.symbol.pointerExternal = external;
1075 // For simple classes, keep the declaration as the external to move around
1076 if(classSym.registered && classSym.registered.type == structClass)
1078 char className[1024];
1079 strcpy(className, "__ecereClass_");
1080 FullClassNameCat(className, classSym.string, true);
1081 MangleClassName(className);
1084 DeclareClass(classSym, className);
1086 external.symbol = classSym;
1087 classSym.pointerExternal = external;
1088 classSym.id = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1089 classSym.idCode = (curExternal && curExternal.symbol) ? curExternal.symbol.idCode : 0;
1093 char className[1024];
1094 strcpy(className, "__ecereClass_");
1095 FullClassNameCat(className, classSym.string, true);
1096 MangleClassName(className);
1098 // TOFIX: TESTING THIS...
1099 classSym.structExternal = external;
1100 DeclareClass(classSym, className);
1101 external.symbol = classSym;
1105 ast->Insert(curExternal ? curExternal.prev : null, external);
1109 classSym.declaring--;
1111 else if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
1113 // TEMPORARY HACK: Pass 3 will move up struct declarations without moving members
1114 // Moved this one up because DeclareClass done later will need it
1117 classSym.declaring++;
1121 if(classSym.registered)
1122 DeclareMembers(classSym.registered, false);
1125 if(classSym.registered && (classSym.registered.type == structClass || classSym.registered.type == noHeadClass))
1128 //ast->Move(classSym.structExternal ? classSym.structExternal : classSym.pointerExternal, curExternal.prev);
1131 if(classSym.structExternal)
1132 ast->Move(classSym.structExternal, curExternal.prev);
1133 ast->Move(classSym.pointerExternal, curExternal.prev);
1135 classSym.id = curExternal.symbol.idCode;
1136 classSym.idCode = curExternal.symbol.idCode;
1137 // external = classSym.pointerExternal;
1138 // external = classSym.structExternal ? classSym.structExternal : classSym.pointerExternal;
1141 classSym.declaring--;
1146 void DeclareProperty(Property prop, char * setName, char * getName)
1148 Symbol symbol = prop.symbol;
1149 char propName[1024];
1151 strcpy(setName, "__ecereProp_");
1152 FullClassNameCat(setName, prop._class.fullName, false);
1153 strcat(setName, "_Set_");
1154 // strcat(setName, prop.name);
1155 FullClassNameCat(setName, prop.name, true);
1157 strcpy(getName, "__ecereProp_");
1158 FullClassNameCat(getName, prop._class.fullName, false);
1159 strcat(getName, "_Get_");
1160 FullClassNameCat(getName, prop.name, true);
1161 // strcat(getName, prop.name);
1163 strcpy(propName, "__ecereProp_");
1164 FullClassNameCat(propName, prop._class.fullName, false);
1165 strcat(propName, "_");
1166 FullClassNameCat(propName, prop.name, true);
1167 // strcat(propName, prop.name);
1169 // To support "char *" property
1170 MangleClassName(getName);
1171 MangleClassName(setName);
1172 MangleClassName(propName);
1174 if(prop._class.type == structClass)
1175 DeclareStruct(prop._class.fullName, false);
1177 if(!symbol || curExternal.symbol.idCode < symbol.id)
1179 bool imported = false;
1180 bool dllImport = false;
1181 if(!symbol || symbol._import)
1186 if(!prop._class.symbol)
1187 prop._class.symbol = FindClass(prop._class.fullName);
1188 classSym = prop._class.symbol;
1189 if(classSym && !classSym._import)
1191 ModuleImport module;
1193 if(prop._class.module)
1194 module = FindModule(prop._class.module);
1196 module = mainModule;
1198 classSym._import = ClassImport
1200 name = CopyString(prop._class.fullName);
1201 isRemote = prop._class.isRemote;
1203 module.classes.Add(classSym._import);
1205 symbol = prop.symbol = Symbol { };
1206 symbol._import = (ClassImport)PropertyImport
1208 name = CopyString(prop.name);
1209 isVirtual = false; //prop.isVirtual;
1210 hasSet = prop.Set ? true : false;
1211 hasGet = prop.Get ? true : false;
1214 classSym._import.properties.Add(symbol._import);
1217 if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
1223 Context context = SetupTemplatesContext(prop._class);
1224 symbol.type = ProcessTypeString(prop.dataTypeString, false);
1225 FinishTemplatesContext(context);
1231 if(!symbol.externalGet || symbol.externalGet.type == functionExternal)
1234 OldList * specifiers, * declarators;
1239 Declarator typeDecl;
1240 bool simple = false;
1242 specifiers = MkList();
1243 declarators = MkList();
1246 ListAdd(params, MkTypeName(MkListOne(MkSpecifierName /*MkClassName*/(prop._class.fullName)),
1247 MkDeclaratorIdentifier(MkIdentifier("this"))));
1249 d = MkDeclaratorIdentifier(MkIdentifier(getName));
1252 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1255 Context context = SetupTemplatesContext(prop._class);
1256 typeDecl = SpecDeclFromString(prop.dataTypeString, specifiers, null);
1257 FinishTemplatesContext(context);
1260 // Make sure the simple _class's type is declared
1261 for(spec = specifiers->first; spec; spec = spec.next)
1263 if(spec.type == nameSpecifier /*SpecifierClass*/)
1265 if((!typeDecl || typeDecl.type == identifierDeclarator))
1267 Symbol classSym = spec.symbol; // FindClass(spec.name);
1268 symbol._class = classSym.registered;
1269 if(classSym.registered && classSym.registered.type == structClass)
1271 DeclareStruct(spec.name, false);
1279 d = PlugDeclarator(typeDecl, d);
1282 ListAdd(params, MkTypeName(specifiers,
1283 PlugDeclarator(typeDecl, MkDeclaratorIdentifier(MkIdentifier("value")))));
1284 specifiers = MkList();
1287 d = MkDeclaratorFunction(d, params);
1291 specifiers->Insert(null, MkSpecifier(EXTERN));
1292 else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1293 specifiers->Insert(null, MkSpecifier(STATIC));
1295 ListAdd(specifiers, MkSpecifier(VOID));
1297 ListAdd(declarators, MkInitDeclarator(d, null));
1299 decl = MkDeclaration(specifiers, declarators);
1301 external = MkExternalDeclaration(decl);
1302 ast->Insert(curExternal.prev, external);
1303 external.symbol = symbol;
1304 symbol.externalGet = external;
1306 ReplaceThisClassSpecifiers(specifiers, prop._class);
1309 FreeDeclarator(typeDecl);
1313 // Move declaration higher...
1314 ast->Move(symbol.externalGet, curExternal.prev);
1321 if(!symbol.externalSet || symbol.externalSet.type == functionExternal)
1324 OldList * specifiers, * declarators;
1329 Declarator typeDecl;
1331 declarators = MkList();
1334 // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1335 if(!prop.conversion || prop._class.type == structClass)
1337 ListAdd(params, MkTypeName(MkListOne(MkSpecifierName/*MkClassName*/(prop._class.fullName)),
1338 MkDeclaratorIdentifier(MkIdentifier("this"))));
1341 specifiers = MkList();
1344 Context context = SetupTemplatesContext(prop._class);
1345 typeDecl = d = SpecDeclFromString(prop.dataTypeString, specifiers,
1346 MkDeclaratorIdentifier(MkIdentifier("value")));
1347 FinishTemplatesContext(context);
1349 ListAdd(params, MkTypeName(specifiers, d));
1351 d = MkDeclaratorIdentifier(MkIdentifier(setName));
1354 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
1355 d = MkDeclaratorFunction(d, params);
1357 // Make sure the simple _class's type is declared
1358 for(spec = specifiers->first; spec; spec = spec.next)
1360 if(spec.type == nameSpecifier /*SpecifierClass*/)
1362 if((!typeDecl || typeDecl.type == identifierDeclarator))
1364 Symbol classSym = spec.symbol; // FindClass(spec.name);
1365 symbol._class = classSym.registered;
1366 if(classSym.registered && classSym.registered.type == structClass)
1367 DeclareStruct(spec.name, false);
1372 ListAdd(declarators, MkInitDeclarator(d, null));
1374 specifiers = MkList();
1377 specifiers->Insert(null, MkSpecifier(EXTERN));
1378 else if(prop._class.symbol && ((Symbol)prop._class.symbol).isStatic)
1379 specifiers->Insert(null, MkSpecifier(STATIC));
1381 // TESTING COMMENTING THIS FIRST LINE OUT, what was the problem? Trying to add noHeadClass here ...
1382 if(!prop.conversion || prop._class.type == structClass)
1383 ListAdd(specifiers, MkSpecifier(VOID));
1385 ListAdd(specifiers, MkSpecifierName/*MkClassName*/(prop._class.fullName));
1387 decl = MkDeclaration(specifiers, declarators);
1389 external = MkExternalDeclaration(decl);
1390 ast->Insert(curExternal.prev, external);
1391 external.symbol = symbol;
1392 symbol.externalSet = external;
1394 ReplaceThisClassSpecifiers(specifiers, prop._class);
1398 // Move declaration higher...
1399 ast->Move(symbol.externalSet, curExternal.prev);
1403 // Property (for Watchers)
1404 if(!symbol.externalPtr)
1408 OldList * specifiers = MkList();
1411 specifiers->Insert(null, MkSpecifier(EXTERN));
1413 specifiers->Insert(null, MkSpecifier(STATIC));
1415 ListAdd(specifiers, MkSpecifierName("Property"));
1418 OldList * list = MkList();
1419 ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
1420 MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1424 strcpy(propName, "__ecerePropM_");
1425 FullClassNameCat(propName, prop._class.fullName, false);
1426 strcat(propName, "_");
1427 // strcat(propName, prop.name);
1428 FullClassNameCat(propName, prop.name, true);
1430 MangleClassName(propName);
1432 ListAdd(list, MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null),
1433 MkDeclaratorIdentifier(MkIdentifier(propName))), null));
1435 decl = MkDeclaration(specifiers, list);
1438 external = MkExternalDeclaration(decl);
1439 ast->Insert(curExternal.prev, external);
1440 external.symbol = symbol;
1441 symbol.externalPtr = external;
1445 // Move declaration higher...
1446 ast->Move(symbol.externalPtr, curExternal.prev);
1449 symbol.id = curExternal.symbol.idCode;
1453 // ***************** EXPRESSION PROCESSING ***************************
1454 public Type Dereference(Type source)
1459 if(source.kind == pointerType || source.kind == arrayType)
1462 source.type.refCount++;
1464 else if(source.kind == classType && !strcmp(source._class.string, "String"))
1472 // Support dereferencing of no head classes for now...
1473 else if(source.kind == classType && source._class && source._class.registered && source._class.registered.type == noHeadClass)
1479 Compiler_Error($"cannot dereference type\n");
1484 static Type Reference(Type source)
1500 void ProcessMemberInitData(MemberInit member, Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
1502 Identifier ident = member.identifiers ? member.identifiers->first : null;
1504 DataMember dataMember = null;
1505 Method method = null;
1506 bool freeType = false;
1508 yylloc = member.loc;
1514 eClass_FindNextMember(_class, curClass, curMember, subMemberStack, subMemberStackPos);
1518 dataMember = *curMember;
1524 DataMember thisMember = (DataMember)eClass_FindProperty(_class, ident.string, privateModule);
1525 DataMember _subMemberStack[256];
1526 int _subMemberStackPos = 0;
1528 // FILL MEMBER STACK
1530 thisMember = eClass_FindDataMember(_class, ident.string, privateModule, _subMemberStack, &_subMemberStackPos);
1533 dataMember = thisMember;
1534 if(curMember && thisMember.memberAccess == publicAccess)
1536 *curMember = thisMember;
1537 *curClass = thisMember._class;
1538 memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
1539 *subMemberStackPos = _subMemberStackPos;
1546 method = eClass_FindMethod(_class, ident.string, privateModule);
1547 if(method && method.type == virtualMethod)
1559 if(!dataMember.dataType && dataMember.dataTypeString)
1561 //Context context = SetupTemplatesContext(dataMember._class);
1562 Context context = SetupTemplatesContext(_class);
1563 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
1564 FinishTemplatesContext(context);
1566 type = dataMember.dataType;
1570 // This is for destination type...
1571 if(!method.dataType)
1572 ProcessMethodType(method);
1573 //DeclareMethod(method);
1574 // method.dataType = ((Symbol)method.symbol)->type;
1575 type = method.dataType;
1578 if(ident && ident.next)
1580 for(ident = ident.next; ident && type; ident = ident.next)
1582 if(type.kind == classType)
1584 dataMember = (DataMember)eClass_FindProperty(type._class.registered, ident.string, privateModule);
1586 dataMember = eClass_FindDataMember(type._class.registered, ident.string, privateModule, null, null);
1588 type = dataMember.dataType;
1590 else if(type.kind == structType || type.kind == unionType)
1593 for(memberType = type.members.first; memberType; memberType = memberType.next)
1595 if(!strcmp(memberType.name, ident.string))
1605 // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
1606 if(type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type && _class.templateArgs /* TODO: Watch out for these _class.templateClass*/)
1609 ClassTemplateParameter curParam = null;
1611 for(sClass = _class; sClass; sClass = sClass.base)
1614 if(sClass.templateClass) sClass = sClass.templateClass;
1615 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
1617 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
1619 for(sClass = sClass.base; sClass; sClass = sClass.base)
1621 if(sClass.templateClass) sClass = sClass.templateClass;
1622 id += sClass.templateParams.count;
1633 ClassTemplateArgument arg = _class.templateArgs[id];
1634 if(arg.dataTypeString)
1637 type = ProcessTypeString(arg.dataTypeString, false);
1639 if(type && _class.templateClass)
1640 type.passAsTemplate = true;
1646 exp.destType = ProcessTypeString(arg.dataTypeString, false);
1647 exp.destType.refCount++;
1653 if(type && type.kind == classType && type._class && type._class.registered && strchr(type._class.registered.fullName, '<'))
1655 Class expClass = type._class.registered;
1656 Class cClass = null;
1661 char templateString[1024];
1662 ClassTemplateParameter param;
1663 sprintf(templateString, "%s<", expClass.templateClass.fullName);
1664 for(cClass = expClass; cClass; cClass = cClass.base)
1667 if(cClass.templateClass) cClass = cClass.templateClass;
1668 for(param = cClass.templateParams.first; param; param = param.next)
1672 ClassTemplateArgument arg;
1673 for(sClass = cClass.base; sClass; sClass = sClass.base)
1675 if(sClass.templateClass) sClass = sClass.templateClass;
1676 id += sClass.templateParams.count;
1678 arg = expClass.templateArgs[id];
1680 for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
1682 ClassTemplateParameter cParam;
1683 //int p = numParams - sClass.templateParams.count;
1686 if(sClass.templateClass) sClass = sClass.templateClass;
1688 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
1690 if(nextClass.templateClass) nextClass = nextClass.templateClass;
1691 p += nextClass.templateParams.count;
1694 for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
1696 if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
1698 if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1700 arg.dataTypeString = _class.templateArgs[p].dataTypeString;
1701 arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
1713 strcat(argument, arg.name.string);
1714 strcat(argument, " = ");
1720 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
1721 char expString[1024];
1722 OldList * specs = MkList();
1723 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
1725 char * string = PrintHexUInt64(arg.expression.ui64);
1726 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
1728 ProcessExpressionType(exp);
1729 ComputeExpression(exp);
1730 expString[0] = '\0';
1731 PrintExpression(exp, expString);
1732 strcat(argument, expString);
1734 FreeExpression(exp);
1739 strcat(argument, arg.member.name);
1742 case TemplateParameterType::type:
1744 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
1745 strcat(argument, arg.dataTypeString);
1751 if(paramCount) strcat(templateString, ", ");
1752 if(lastParam != p - 1)
1754 strcat(templateString, param.name);
1755 strcat(templateString, " = ");
1757 strcat(templateString, argument);
1766 int len = strlen(templateString);
1767 if(templateString[len-1] == '<')
1771 if(templateString[len-1] == '>')
1772 templateString[len++] = ' ';
1773 templateString[len++] = '>';
1775 templateString[len++] = '\0';
1778 Context context = SetupTemplatesContext(_class);
1779 if(freeType) FreeType(type);
1780 type = ProcessTypeString(templateString, false);
1782 FinishTemplatesContext(context);
1786 if(method && member.initializer && member.initializer.type == expInitializer && member.initializer.exp)
1788 ProcessExpressionType(member.initializer.exp);
1789 if(!member.initializer.exp.expType)
1793 char expString[10240];
1794 expString[0] = '\0';
1795 PrintExpression(member.initializer.exp, expString);
1796 ChangeCh(expString, '\n', ' ');
1797 Compiler_Error($"unresolved symbol used as an instance method %s\n", expString);
1800 //else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
1801 else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
1803 Compiler_Error($"incompatible instance method %s\n", ident.string);
1806 else if(member.initializer)
1809 FreeType(member.exp.destType);
1810 member.exp.destType = type;
1811 if(member.exp.destType)
1812 member.exp.destType.refCount++;
1813 ProcessExpressionType(member.exp);
1816 ProcessInitializer(member.initializer, type);
1818 if(freeType) FreeType(type);
1822 if(_class && _class.type == unitClass)
1824 if(member.initializer)
1827 FreeType(member.exp.destType);
1828 member.exp.destType = MkClassType(_class.fullName);
1829 ProcessExpressionType(member.initializer, type);
1831 Type type = MkClassType(_class.fullName);
1832 ProcessInitializer(member.initializer, type);
1838 if(member.initializer)
1840 //ProcessExpressionType(member.exp);
1841 ProcessInitializer(member.initializer, null);
1847 Compiler_Error($"couldn't find virtual method %s in class %s\n", ident.string, _class.fullName);
1851 Compiler_Error($"couldn't find member %s in class %s\n", ident.string, _class.fullName);
1853 eClass_AddDataMember(_class, ident.string, "int", 0, 0, publicAccess);
1857 Compiler_Error($"too many initializers for instantiation of class %s\n", _class.fullName);
1862 void ProcessInstantiationType(Instantiation inst)
1867 MembersInit members;
1868 Symbol classSym; // = inst._class.symbol; // FindClass(inst._class.name);
1871 /*if(!inst._class.symbol)
1872 inst._class.symbol = FindClass(inst._class.name);*/
1873 classSym = inst._class.symbol;
1874 _class = classSym ? classSym.registered : null;
1876 // DANGER: Patch for mutex not declaring its struct when not needed
1877 if(!_class || _class.type != noHeadClass)
1878 DeclareStruct(inst._class.name, false); //_class && _class.type == noHeadClass);
1880 afterExternal = afterExternal ? afterExternal : curExternal;
1883 ProcessExpressionType(inst.exp);
1885 inst.isConstant = true;
1888 DataMember curMember = null;
1889 Class curClass = null;
1890 DataMember subMemberStack[256];
1891 int subMemberStackPos = 0;
1893 for(members = inst.members->first; members; members = members.next)
1895 switch(members.type)
1897 case methodMembersInit:
1900 static uint instMethodID = 0;
1901 External external = curExternal;
1902 Context context = curContext;
1903 Declarator declarator = members.function.declarator;
1904 Identifier nameID = GetDeclId(declarator);
1905 char * unmangled = nameID ? nameID.string : null;
1907 External createdExternal = null;
1912 //members.function.dontMangle = true;
1913 strcpy(name, "__ecereInstMeth_");
1914 FullClassNameCat(name, _class ? _class.fullName : "_UNKNOWNCLASS", false);
1916 strcat(name, nameID.string);
1918 sprintf(number, "_%08d", instMethodID++);
1919 strcat(name, number);
1920 nameID.string = CopyString(name);
1923 // Do modifications here...
1926 Symbol symbol = declarator.symbol;
1927 Method method = eClass_FindMethod(_class, unmangled, privateModule);
1929 if(method && method.type == virtualMethod)
1931 symbol.method = method;
1932 ProcessMethodType(method);
1934 if(!symbol.type.thisClass)
1936 if(method.dataType.thisClass && currentClass &&
1937 eClass_IsDerived(currentClass, method.dataType.thisClass.registered))
1939 if(!currentClass.symbol)
1940 currentClass.symbol = FindClass(currentClass.fullName);
1941 symbol.type.thisClass = currentClass.symbol;
1946 _class.symbol = FindClass(_class.fullName);
1947 symbol.type.thisClass = _class.symbol;
1950 // TESTING THIS HERE:
1951 DeclareType(symbol.type, true, true);
1956 Compiler_Error($"couldn't find virtual method %s in class %s\n",
1957 unmangled, classSym.string);
1961 //declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
1962 createdExternal = ProcessClassFunction(classSym ? classSym.registered : null, members.function, ast, afterExternal, true);
1966 FreeSpecifier(nameID._class);
1967 nameID._class = null;
1973 Type type = declarator.symbol.type;
1974 External oldExternal = curExternal;
1976 // *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
1977 // *** It was commented out for problems such as
1979 class VirtualDesktop : Window
1981 clientSize = Size { };
1992 // Commented Out: Good for bet.ec in Poker (Otherwise: obj\bet.c:187: error: `currentBet' undeclared (first use in this function))
1994 declarator.symbol.id = declarator.symbol.idCode = curExternal.symbol.idCode;
1997 if(strcmp(declarator.symbol.string, name))
1999 printf("TOCHECK: Look out for this\n");
2000 delete declarator.symbol.string;
2001 declarator.symbol.string = CopyString(name);
2004 if(!declarator.symbol.parent && globalContext.symbols.root != (BTNode)declarator.symbol)
2006 printf("TOCHECK: Will this ever be in a list? Yes.\n");
2007 excludedSymbols->Remove(declarator.symbol);
2008 globalContext.symbols.Add((BTNode)declarator.symbol);
2009 if(strstr(declarator.symbol.string), "::")
2010 globalContext.hasNameSpace = true;
2015 //curExternal = curExternal.prev;
2016 //afterExternal = afterExternal->next;
2018 //ProcessFunction(afterExternal->function);
2020 //curExternal = afterExternal;
2022 External externalDecl;
2023 externalDecl = MkExternalDeclaration(null);
2024 ast->Insert(oldExternal.prev, externalDecl);
2026 // Which function does this process?
2027 if(createdExternal.function)
2029 ProcessFunction(createdExternal.function);
2031 //curExternal = oldExternal;
2034 //Declaration decl = MkDeclaration(members.function.specifiers, MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2036 Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
2037 MkListOne(MkInitDeclarator(CopyDeclarator(declarator), null)));
2039 //externalDecl = MkExternalDeclaration(decl);
2041 //***** ast->Insert(external.prev, externalDecl);
2042 //ast->Insert(curExternal.prev, externalDecl);
2043 externalDecl.declaration = decl;
2044 if(decl.symbol && !decl.symbol.pointerExternal)
2045 decl.symbol.pointerExternal = externalDecl;
2047 // Trying this out...
2048 declarator.symbol.pointerExternal = externalDecl;
2055 curExternal = declarator.symbol.pointerExternal;
2056 ProcessFunction((FunctionDefinition)members.function);
2058 curExternal = external;
2059 curContext = context;
2063 FreeClassFunction(members.function);
2065 // In this pass, turn this into a MemberInitData
2066 exp = QMkExpId(name);
2067 members.type = dataMembersInit;
2068 members.dataMembers = MkListOne(MkMemberInit(MkListOne(MkIdentifier(unmangled)), MkInitializerAssignment(exp)));
2074 case dataMembersInit:
2076 if(members.dataMembers && classSym)
2079 Location oldyyloc = yylloc;
2080 for(member = members.dataMembers->first; member; member = member.next)
2082 ProcessMemberInitData(member, classSym.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
2083 if(member.initializer && !member.initializer.isConstant)
2084 inst.isConstant = false;
2096 static void DeclareType(Type type, bool declarePointers, bool declareParams)
2098 // OPTIMIZATIONS: TESTING THIS...
2101 if(type.kind == functionType)
2106 for(param = type.params.first; param; param = param.next)
2107 DeclareType(param, declarePointers, true);
2109 DeclareType(type.returnType, declarePointers, true);
2111 else if(type.kind == pointerType && declarePointers)
2112 DeclareType(type.type, declarePointers, false);
2113 else if(type.kind == classType)
2115 if(type._class.registered && (type._class.registered.type == structClass || type._class.registered.type == noHeadClass) && !type._class.declaring)
2116 DeclareStruct(type._class.registered.fullName, type._class.registered.type == noHeadClass);
2118 else if(type.kind == structType || type.kind == unionType)
2121 for(member = type.members.first; member; member = member.next)
2122 DeclareType(member, false, false);
2124 else if(type.kind == arrayType)
2125 DeclareType(type.arrayType, declarePointers, false);
2129 ClassTemplateArgument * FindTemplateArg(Class _class, TemplateParameter param)
2131 ClassTemplateArgument * arg = null;
2133 ClassTemplateParameter curParam = null;
2135 for(sClass = _class; sClass; sClass = sClass.base)
2138 if(sClass.templateClass) sClass = sClass.templateClass;
2139 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
2141 if(curParam.type == TemplateParameterType::type && !strcmp(param.identifier.string, curParam.name))
2143 for(sClass = sClass.base; sClass; sClass = sClass.base)
2145 if(sClass.templateClass) sClass = sClass.templateClass;
2146 id += sClass.templateParams.count;
2156 arg = &_class.templateArgs[id];
2157 if(arg && param.type == type)
2158 arg->dataTypeClass = eSystem_FindClass(_class.module, arg->dataTypeString);
2163 public Context SetupTemplatesContext(Class _class)
2165 Context context = PushContext();
2166 context.templateTypesOnly = true;
2167 if(_class.symbol && ((Symbol)_class.symbol).templateParams)
2169 TemplateParameter param = ((Symbol)_class.symbol).templateParams->first;
2170 for(; param; param = param.next)
2172 if(param.type == type && param.identifier)
2174 TemplatedType type { key = (uintptr)param.identifier.string, param = param };
2175 curContext.templateTypes.Add((BTNode)type);
2182 for(sClass = _class; sClass; sClass = sClass.base)
2184 ClassTemplateParameter p;
2185 for(p = sClass.templateParams.first; p; p = p.next)
2187 //OldList * specs = MkList();
2188 //Declarator decl = null;
2189 //decl = SpecDeclFromString(p.dataTypeString, specs, null);
2192 TemplateParameter param = p.param;
2196 // ADD DATA TYPE HERE...
2197 p.param = param = TemplateParameter
2199 identifier = MkIdentifier(p.name), type = p.type,
2200 dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
2203 type = TemplatedType { key = (uintptr)p.name, param = param };
2204 curContext.templateTypes.Add((BTNode)type);
2212 public void FinishTemplatesContext(Context context)
2214 PopContext(context);
2215 FreeContext(context);
2219 public void ProcessMethodType(Method method)
2221 if(!method.dataType)
2223 Context context = SetupTemplatesContext(method._class);
2225 method.dataType = ProcessTypeString(method.dataTypeString, false);
2227 FinishTemplatesContext(context);
2229 if(method.type != virtualMethod && method.dataType)
2231 if(!method.dataType.thisClass && !method.dataType.staticMethod)
2233 if(!method._class.symbol)
2234 method._class.symbol = FindClass(method._class.fullName);
2235 method.dataType.thisClass = method._class.symbol;
2239 // Why was this commented out? Working fine without now...
2242 if(method.dataType.kind == functionType && !method.dataType.staticMethod && !method.dataType.thisClass)
2243 method.dataType.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2250 char * par = strstr(type, "(");
2251 char * classOp = null;
2256 for(c = par-type-1; c >= 0; c++)
2258 if(type[c] == ':' && type[c+1] == ':')
2260 classOp = type + c - 1;
2261 for(c = c-1; c >=0 && !isspace(type[c]); c--)
2268 else if(!isspace(type[c]))
2275 int typeLen = strlen(type);
2276 memcpy(temp, classOp, classOpLen);
2277 temp[classOpLen] = '\0';
2279 _class = eSystem_FindClass(module, temp);
2282 method.dataTypeString = new char[typeLen - classOpLen + 1];
2283 memcpy(method.dataTypeString, type, classOp - type);
2284 memcpy(method.dataTypeString + (classOp - type), classOp + classOpLen, typeLen - (classOp - type + classOpLen));
2287 method.dataTypeString = type;
2293 public void ProcessPropertyType(Property prop)
2297 Context context = SetupTemplatesContext(prop._class);
2298 prop.dataType = ProcessTypeString(prop.dataTypeString, false);
2299 FinishTemplatesContext(context);
2303 public void DeclareMethod(Method method, char * name)
2305 Symbol symbol = method.symbol;
2306 if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
2308 bool imported = false;
2309 bool dllImport = false;
2311 if(!method.dataType)
2312 method.dataType = ProcessTypeString(method.dataTypeString, false);
2314 if(!symbol || symbol._import || method.type == virtualMethod)
2316 if(!symbol || method.type == virtualMethod)
2319 if(!method._class.symbol)
2320 method._class.symbol = FindClass(method._class.fullName);
2321 classSym = method._class.symbol;
2322 if(!classSym._import)
2324 ModuleImport module;
2326 if(method._class.module && method._class.module.name)
2327 module = FindModule(method._class.module);
2329 module = mainModule;
2330 classSym._import = ClassImport
2332 name = CopyString(method._class.fullName);
2333 isRemote = method._class.isRemote;
2335 module.classes.Add(classSym._import);
2339 symbol = method.symbol = Symbol { };
2343 symbol._import = (ClassImport)MethodImport
2345 name = CopyString(method.name);
2346 isVirtual = method.type == virtualMethod;
2348 classSym._import.methods.Add(symbol._import);
2352 // Set the symbol type
2356 type.thisClass = method._class.symbol; // FindClass(method._class.fullName);
2358 else if(type.thisClass == (void *)-1)
2360 type.thisClass = null;
2363 // symbol.type = ProcessTypeString(method.dataTypeString, false);
2364 symbol.type = method.dataType;
2365 if(symbol.type) symbol.type.refCount++;
2368 if(!method.thisClass || strcmp(method.thisClass, "void"))
2369 symbol.type.params.Insert(null,
2370 MkClassType(method.thisClass ? method.thisClass : method._class.fullName));
2373 if(!method.dataType.dllExport)
2376 if(method._class.module != privateModule && method._class.module.importType != staticImport)
2382 if(!method.dataType)
2383 method.dataType = ((Symbol)method.symbol).type;
2384 //ProcessMethodType(method);
2387 if(method.type != virtualMethod && method.dataType)
2388 DeclareType(method.dataType, true, true);
2390 if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2392 // We need a declaration here :)
2394 OldList * specifiers, * declarators;
2396 Declarator funcDecl;
2399 specifiers = MkList();
2400 declarators = MkList();
2404 ListAdd(specifiers, MkSpecifier(EXTERN));
2405 else if(method._class.symbol && ((Symbol)method._class.symbol).isStatic)
2406 ListAdd(specifiers, MkSpecifier(STATIC));
2408 if(method.type == virtualMethod)
2410 ListAdd(specifiers, MkSpecifier(INT));
2411 d = MkDeclaratorIdentifier(MkIdentifier(name));
2415 d = MkDeclaratorIdentifier(MkIdentifier(name));
2418 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2420 Context context = SetupTemplatesContext(method._class);
2421 d = SpecDeclFromString(method.dataTypeString, specifiers, d);
2422 FinishTemplatesContext(context);
2424 funcDecl = GetFuncDecl(d);
2428 Specifier spec, next;
2429 for(spec = specifiers->first; spec; spec = next)
2432 if(spec.type == extendedSpecifier)
2434 specifiers->Remove(spec);
2435 FreeSpecifier(spec);
2440 // Add this parameter if not a static method
2441 if(method.dataType && !method.dataType.staticMethod)
2443 if(funcDecl && funcDecl.function.parameters && funcDecl.function.parameters->count)
2445 Class _class = method.dataType.thisClass ? method.dataType.thisClass.registered : method._class;
2446 TypeName thisParam = MkTypeName(MkListOne(
2447 MkSpecifierName/*MkClassName*/(method.dataType.thisClass ? method.dataType.thisClass.string : method._class.fullName)),
2448 (_class && _class.type == systemClass) ? MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("this"))) : MkDeclaratorIdentifier(MkIdentifier("this")));
2449 TypeName firstParam = ((TypeName)funcDecl.function.parameters->first);
2450 Specifier firstSpec = firstParam.qualifiers ? firstParam.qualifiers->first : null;
2452 if(firstSpec && firstSpec.type == baseSpecifier && firstSpec.specifier == VOID && !firstParam.declarator)
2454 TypeName param = funcDecl.function.parameters->first;
2455 funcDecl.function.parameters->Remove(param);
2456 FreeTypeName(param);
2459 if(!funcDecl.function.parameters)
2460 funcDecl.function.parameters = MkList();
2461 funcDecl.function.parameters->Insert(null, thisParam);
2464 // Make sure we don't have empty parameter declarations for static methods...
2466 else if(!funcDecl.function.parameters)
2468 funcDecl.function.parameters = MkList();
2469 funcDecl.function.parameters->Insert(null,
2470 MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2474 ProcessDeclarator(d);
2476 ListAdd(declarators, MkInitDeclarator(d, null));
2478 decl = MkDeclaration(specifiers, declarators);
2480 ReplaceThisClassSpecifiers(specifiers, method._class);
2482 // Keep a different symbol for the function definition than the declaration...
2483 if(symbol.pointerExternal)
2485 Symbol functionSymbol { };
2489 *functionSymbol = *symbol;
2490 functionSymbol.string = CopyString(symbol.string);
2491 if(functionSymbol.type)
2492 functionSymbol.type.refCount++;
2495 excludedSymbols->Add(functionSymbol);
2496 symbol.pointerExternal.symbol = functionSymbol;
2498 external = MkExternalDeclaration(decl);
2500 ast->Insert(curExternal ? curExternal.prev : null, external);
2501 external.symbol = symbol;
2502 symbol.pointerExternal = external;
2506 // Move declaration higher...
2507 ast->Move(symbol.pointerExternal, curExternal.prev);
2510 symbol.id = curExternal ? curExternal.symbol.idCode : MAXINT;
2514 char * ReplaceThisClass(Class _class)
2516 if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2520 ClassTemplateParameter param;
2523 char className[1024];
2524 strcpy(className, _class.fullName);
2525 for(param = _class.templateParams.first; param; param = param.next)
2527 // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2529 if(first) strcat(className, "<");
2530 if(!first) strcat(className, ", ");
2531 if(lastParam + 1 != p)
2533 strcat(className, param.name);
2534 strcat(className, " = ");
2536 strcat(className, param.name);
2544 int len = strlen(className);
2545 if(className[len-1] == '>') className[len++] = ' ';
2546 className[len++] = '>';
2547 className[len++] = '\0';
2549 return CopyString(className);
2552 return CopyString(_class.fullName);
2555 Type ReplaceThisClassType(Class _class)
2557 if(thisClassParams && _class.templateParams.count && !_class.templateClass)
2561 ClassTemplateParameter param;
2563 char className[1024];
2564 strcpy(className, _class.fullName);
2566 for(param = _class.templateParams.first; param; param = param.next)
2568 // if((!param.defaultArg.dataTypeString && !param.defaultArg.expression.ui64))
2570 if(first) strcat(className, "<");
2571 if(!first) strcat(className, ", ");
2572 if(lastParam + 1 != p)
2574 strcat(className, param.name);
2575 strcat(className, " = ");
2577 strcat(className, param.name);
2585 int len = strlen(className);
2586 if(className[len-1] == '>') className[len++] = ' ';
2587 className[len++] = '>';
2588 className[len++] = '\0';
2590 return MkClassType(className);
2591 //return ProcessTypeString(className, false);
2595 return MkClassType(_class.fullName);
2596 //return ProcessTypeString(_class.fullName, false);
2600 void ReplaceThisClassSpecifiers(OldList specs, Class _class)
2602 if(specs != null && _class)
2605 for(spec = specs.first; spec; spec = spec.next)
2607 if(spec.type == baseSpecifier && spec.specifier == THISCLASS)
2609 spec.type = nameSpecifier;
2610 spec.name = ReplaceThisClass(_class);
2611 spec.symbol = FindClass(spec.name); //_class.symbol;
2617 // Returns imported or not
2618 bool DeclareFunction(GlobalFunction function, char * name)
2620 Symbol symbol = function.symbol;
2621 if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2623 bool imported = false;
2624 bool dllImport = false;
2626 if(!function.dataType)
2628 function.dataType = ProcessTypeString(function.dataTypeString, false);
2629 if(!function.dataType.thisClass)
2630 function.dataType.staticMethod = true;
2637 ModuleImport module = FindModule(function.module);
2638 // WARNING: This is not added anywhere...
2639 symbol = function.symbol = Symbol { };
2643 if(!function.dataType.dllExport)
2645 symbol._import = (ClassImport)FunctionImport { name = CopyString(function.name) };
2646 module.functions.Add(symbol._import);
2649 // Set the symbol type
2651 symbol.type = ProcessTypeString(function.dataTypeString, false);
2652 if(!symbol.type.thisClass)
2653 symbol.type.staticMethod = true;
2656 imported = symbol._import ? true : false;
2657 if(imported && function.module != privateModule && function.module.importType != staticImport)
2661 DeclareType(function.dataType, true, true);
2665 if(!symbol.pointerExternal || symbol.pointerExternal.type == functionExternal)
2667 // We need a declaration here :)
2669 OldList * specifiers, * declarators;
2671 Declarator funcDecl;
2674 specifiers = MkList();
2675 declarators = MkList();
2678 ListAdd(specifiers, MkSpecifier(EXTERN));
2681 ListAdd(specifiers, MkSpecifier(STATIC));
2684 d = MkDeclaratorIdentifier(MkIdentifier(imported ? name : function.name));
2687 d = MkDeclaratorBrackets(MkDeclaratorPointer(MkPointer(null, null), d));
2689 d = SpecDeclFromString(function.dataTypeString, specifiers, d);
2690 // TAKE OUT THE DLL EXPORT IF STATICALLY IMPORTED:
2691 if(function.module.importType == staticImport)
2694 for(spec = specifiers->first; spec; spec = spec.next)
2695 if(spec.type == extendedSpecifier && spec.extDecl && spec.extDecl.type == extDeclString && !strcmp(spec.extDecl.s, "dllexport"))
2697 specifiers->Remove(spec);
2698 FreeSpecifier(spec);
2703 funcDecl = GetFuncDecl(d);
2705 // Make sure we don't have empty parameter declarations for static methods...
2706 if(funcDecl && !funcDecl.function.parameters)
2708 funcDecl.function.parameters = MkList();
2709 funcDecl.function.parameters->Insert(null,
2710 MkTypeName(MkListOne(MkSpecifier(VOID)),null));
2713 ListAdd(declarators, MkInitDeclarator(d, null));
2716 Context oldCtx = curContext;
2717 curContext = globalContext;
2718 decl = MkDeclaration(specifiers, declarators);
2719 curContext = oldCtx;
2722 // Keep a different symbol for the function definition than the declaration...
2723 if(symbol.pointerExternal)
2725 Symbol functionSymbol { };
2728 *functionSymbol = *symbol;
2729 functionSymbol.string = CopyString(symbol.string);
2730 if(functionSymbol.type)
2731 functionSymbol.type.refCount++;
2734 excludedSymbols->Add(functionSymbol);
2736 symbol.pointerExternal.symbol = functionSymbol;
2738 external = MkExternalDeclaration(decl);
2740 ast->Insert(curExternal.prev, external);
2741 external.symbol = symbol;
2742 symbol.pointerExternal = external;
2746 // Move declaration higher...
2747 ast->Move(symbol.pointerExternal, curExternal.prev);
2751 symbol.id = curExternal.symbol.idCode;
2754 return (symbol && symbol._import && function.module != privateModule && function.module.importType != staticImport) ? true : false;
2757 void DeclareGlobalData(GlobalData data)
2759 Symbol symbol = data.symbol;
2760 if(curExternal && (!symbol || symbol.id > curExternal.symbol.idCode))
2765 symbol = data.symbol = Symbol { };
2768 data.dataType = ProcessTypeString(data.dataTypeString, false);
2769 DeclareType(data.dataType, true, true);
2772 if(!symbol.pointerExternal)
2774 // We need a declaration here :)
2776 OldList * specifiers, * declarators;
2780 specifiers = MkList();
2781 declarators = MkList();
2783 ListAdd(specifiers, MkSpecifier(EXTERN));
2784 d = MkDeclaratorIdentifier(MkIdentifier(data.fullName));
2785 d = SpecDeclFromString(data.dataTypeString, specifiers, d);
2787 ListAdd(declarators, MkInitDeclarator(d, null));
2789 decl = MkDeclaration(specifiers, declarators);
2790 external = MkExternalDeclaration(decl);
2792 ast->Insert(curExternal.prev, external);
2793 external.symbol = symbol;
2794 symbol.pointerExternal = external;
2798 // Move declaration higher...
2799 ast->Move(symbol.pointerExternal, curExternal.prev);
2803 symbol.id = curExternal.symbol.idCode;
2808 class Conversion : struct
2810 Conversion prev, next;
2816 public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
2820 // Property convert;
2822 if(source.kind == templateType && dest.kind != templateType)
2824 Type type = ProcessTemplateParameterType(source.templateParameter);
2825 if(type) source = type;
2828 if(dest.kind == templateType && source.kind != templateType)
2830 Type type = ProcessTemplateParameterType(dest.templateParameter);
2831 if(type) dest = type;
2834 if((dest.classObjectType == typedObject && source.classObjectType != anyObject) || (dest.classObjectType == anyObject && source.classObjectType != typedObject))
2839 if(source.classObjectType == anyObject && dest.classObjectType != typedObject)
2844 if((dest.kind == structType && source.kind == structType) ||
2845 (dest.kind == unionType && source.kind == unionType))
2847 if((dest.enumName && source.enumName && !strcmp(dest.enumName, source.enumName)) ||
2848 (source.members.first && source.members.first == dest.members.first))
2852 if(dest.kind == ellipsisType && source.kind != voidType)
2855 if(dest.kind == pointerType && dest.type.kind == voidType &&
2856 ((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))
2857 || source.kind == subClassType || source.kind == pointerType || source.kind == arrayType || source.kind == functionType || source.kind == thisClassType)
2859 /*source.kind != voidType && source.kind != structType && source.kind != unionType */
2861 /*&& (source.kind != classType /-*|| source._class.registered.type != structClass)*/)
2863 if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
2864 ((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))
2865 || dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
2867 /* dest.kind != voidType && dest.kind != structType && dest.kind != unionType */
2869 /*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
2872 if(((source.kind == classType && dest.kind == classType) || (source.kind == subClassType && dest.kind == subClassType)) && source._class)
2874 if(source._class.registered && source._class.registered.type == unitClass)
2876 if(conversions != null)
2878 if(source._class.registered == dest._class.registered)
2883 Class sourceBase, destBase;
2884 for(sourceBase = source._class.registered; sourceBase && sourceBase.base.type != systemClass; sourceBase = sourceBase.base);
2885 for(destBase = dest._class.registered; destBase && destBase.base.type != systemClass; destBase = destBase.base);
2886 if(sourceBase == destBase)
2890 // Don't match enum inheriting from other enum if resolving enumeration values
2891 // TESTING: !dest.classObjectType
2892 else if(source._class && dest._class && (dest.classObjectType == source.classObjectType || !dest.classObjectType) &&
2894 (!source._class.registered || source._class.registered.type != enumClass) ||
2895 (!dest._class.registered || dest._class.registered.type != enumClass)) && eClass_IsDerived(source._class.registered, dest._class.registered))
2899 // Added this so that DefinedColor = Color doesn't go through ColorRGB property
2901 dest._class && dest._class.registered && dest._class.registered.type == enumClass &&
2902 source._class && source._class.registered && source._class.registered.type != enumClass)
2904 if(eClass_IsDerived(dest._class.registered, source._class.registered))
2912 // JUST ADDED THIS...
2913 if(source.kind == subClassType && dest.kind == classType && dest._class && !strcmp(dest._class.string, "ecere::com::Class"))
2918 // Just added this for Straight conversion of ColorAlpha => Color
2919 if(source.kind == classType)
2922 for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
2925 for(convert = _class.conversions.first; convert; convert = convert.next)
2927 if(convert.memberAccess == publicAccess || _class.module == privateModule)
2929 Conversion after = (conversions != null) ? conversions.last : null;
2931 if(!convert.dataType)
2932 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
2933 if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
2935 if(!conversions && !convert.Get)
2937 else if(conversions != null)
2939 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
2940 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
2941 (dest.kind != classType || dest._class.registered != _class.base))
2945 Conversion conv { convert = convert, isGet = true };
2946 // conversions.Add(conv);
2947 conversions.Insert(after, conv);
2959 if(dest.kind == classType)
2962 for(_class = dest._class ? dest._class.registered : null; _class; _class = _class.base)
2965 for(convert = _class.conversions.first; convert; convert = convert.next)
2967 if(convert.memberAccess == publicAccess || _class.module == privateModule)
2969 // Conversion after = (conversions != null) ? conversions.last : null;
2971 if(!convert.dataType)
2972 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
2973 // Just added this equality check to prevent recursion.... Make it safer?
2974 // Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
2975 if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
2977 if(!conversions && !convert.Set)
2979 else if(conversions != null)
2981 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
2982 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
2983 (source.kind != classType || source._class.registered != _class.base))
2987 // *** Testing this! ***
2988 Conversion conv { convert = convert };
2989 conversions.Add(conv);
2990 //conversions.Insert(after, conv);
2998 /*if(dest._class.registered && !strcmp(dest._class.registered.name, "bool"))
3000 if(source.kind != voidType && source.kind != structType && source.kind != unionType &&
3001 (source.kind != classType || source._class.registered.type != structClass))
3005 // TESTING THIS... IS THIS OK??
3006 if(enumBaseType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3008 if(!dest._class.registered.dataType)
3009 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3010 // Only support this for classes...
3011 if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
3012 !strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
3014 if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3023 if(source.kind == classType)
3026 for(_class = source._class ? source._class.registered : null; _class; _class = _class.base)
3029 for(convert = _class.conversions.first; convert; convert = convert.next)
3031 if(convert.memberAccess == publicAccess || _class.module == privateModule)
3033 Conversion after = (conversions != null) ? conversions.last : null;
3035 if(!convert.dataType)
3036 convert.dataType = ProcessTypeString(convert.dataTypeString, false);
3037 if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
3039 if(!conversions && !convert.Get)
3041 else if(conversions != null)
3043 if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
3044 convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
3045 (dest.kind != classType || dest._class.registered != _class.base))
3049 Conversion conv { convert = convert, isGet = true };
3051 // conversions.Add(conv);
3052 conversions.Insert(after, conv);
3061 // TESTING THIS... IS THIS OK??
3062 if(enumBaseType && source._class && source._class.registered && source._class.registered.type == enumClass)
3064 if(!source._class.registered.dataType)
3065 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3066 if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
3074 if(source.kind == classType || source.kind == subClassType)
3076 else if(dest.kind == source.kind &&
3077 (dest.kind != structType && dest.kind != unionType &&
3078 dest.kind != functionType && dest.kind != arrayType && dest.kind != pointerType && dest.kind != methodType))
3080 // RECENTLY ADDED THESE
3081 else if(dest.kind == doubleType && source.kind == floatType)
3083 else if(dest.kind == shortType && source.kind == charType)
3085 else if(dest.kind == intType && (source.kind == shortType || source.kind == charType))
3087 else if(dest.kind == int64Type && (source.kind == shortType || source.kind == charType || source.kind == intType))
3089 else if(dest.kind == intPtrType && (source.kind == shortType || source.kind == charType || source.kind == intType))
3091 else if(source.kind == enumType &&
3092 (dest.kind == intType || dest.kind == shortType || dest.kind == charType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType))
3094 else if(dest.kind == enumType &&
3095 (source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType))
3097 else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) &&
3098 ((source.kind == functionType || (source.kind == pointerType && source.type.kind == functionType) || source.kind == methodType)))
3100 Type paramSource, paramDest;
3102 if(dest.kind == methodType)
3103 owningClassDest = dest.methodClass ? dest.methodClass : dest.method._class;
3104 if(source.kind == methodType)
3105 owningClassSource = source.methodClass ? source.methodClass : source.method._class;
3107 if(dest.kind == pointerType && dest.type.kind == functionType) dest = dest.type;
3108 if(source.kind == pointerType && source.type.kind == functionType) source = source.type;
3109 if(dest.kind == methodType)
3110 dest = dest.method.dataType;
3111 if(source.kind == methodType)
3112 source = source.method.dataType;
3114 paramSource = source.params.first;
3115 if(paramSource && paramSource.kind == voidType) paramSource = null;
3116 paramDest = dest.params.first;
3117 if(paramDest && paramDest.kind == voidType) paramDest = null;
3120 if((dest.staticMethod || (!dest.thisClass && !owningClassDest)) &&
3121 !(source.staticMethod || (!source.thisClass && !owningClassSource)))
3123 // Source thisClass must be derived from destination thisClass
3124 if(!paramDest || (!(paramDest.kind == pointerType && paramDest.type && paramDest.type.kind == voidType) && (paramDest.kind != classType ||
3125 !eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource,paramDest._class.registered))))
3127 if(paramDest && paramDest.kind == classType)
3128 Compiler_Error($"method class must be derived from %s\n", paramDest._class.string);
3130 Compiler_Error($"method class should not take an object\n");
3133 paramDest = paramDest.next;
3135 else if(!dest.staticMethod && (dest.thisClass || owningClassDest))
3137 if((source.staticMethod || (!source.thisClass && !owningClassSource)))
3141 if(!paramSource || paramSource.kind != classType || !eClass_IsDerived(paramSource._class.registered,dest.thisClass.registered))
3143 Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3149 // THIS WAS BACKWARDS:
3150 // if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(owningClassDest, paramSource._class.registered)))
3151 if(!paramSource || paramSource.kind != classType || (owningClassDest && !eClass_IsDerived(paramSource._class.registered, owningClassDest)))
3154 Compiler_Error($"%s expected to be derived from method class\n", owningClassDest.fullName);
3156 Compiler_Error($"overriding class expected to be derived from method class\n");
3160 paramSource = paramSource.next;
3166 // Source thisClass must be derived from destination thisClass
3167 if(!eClass_IsDerived(source.thisClass ? source.thisClass.registered : owningClassSource, dest.thisClass.registered))
3169 Compiler_Error($"method class must be derived from %s\n", dest.thisClass.string);
3175 // THIS WAS BACKWARDS TOO??
3176 // if(source.thisClass && owningClassDest && !eClass_IsDerived(owningClassDest, source.thisClass.registered))
3177 if(source.thisClass && source.thisClass.registered && owningClassDest && !eClass_IsDerived(source.thisClass.registered, owningClassDest))
3180 Compiler_Error($"%s expected to be derived from method class\n", /*owningClass.name*/ source.thisClass.registered.fullName);
3182 //Compiler_Error($"overriding class expected to be derived from method class\n");
3190 // Source return type must be derived from destination return type
3191 if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
3193 Compiler_Warning($"incompatible return type for function\n");
3199 for(; paramDest; paramDest = paramDest.next)
3203 //Compiler_Warning($"not enough parameters\n");
3204 Compiler_Error($"not enough parameters\n");
3208 Type paramDestType = paramDest;
3209 Type paramSourceType = paramSource;
3210 Type type = paramDestType;
3212 // *** WORKING CODE: TESTING THIS HERE FOR TEMPLATES ***
3213 if(paramDest.kind == templateType && paramDest.templateParameter.type == TemplateParameterType::type && owningClassSource &&
3214 paramSource.kind != templateType)
3217 ClassTemplateParameter curParam = null;
3219 for(sClass = owningClassSource; sClass; sClass = sClass.base)
3222 if(sClass.templateClass) sClass = sClass.templateClass;
3223 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3225 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
3227 for(sClass = sClass.base; sClass; sClass = sClass.base)
3229 if(sClass.templateClass) sClass = sClass.templateClass;
3230 id += sClass.templateParams.count;
3241 ClassTemplateArgument arg = owningClassSource.templateArgs[id];
3242 paramDestType = type = ProcessTypeString(arg.dataTypeString, false);
3246 // paramDest must be derived from paramSource
3247 if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) &&
3248 (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
3252 PrintType(paramDest, type, false, true);
3253 Compiler_Warning($"incompatible parameter %s (expected %s)\n", paramSource.name, type);
3255 if(paramDestType != paramDest)
3256 FreeType(paramDestType);
3259 if(paramDestType != paramDest)
3260 FreeType(paramDestType);
3263 paramSource = paramSource.next;
3267 Compiler_Error($"too many parameters\n");
3272 else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) && (source.kind == pointerType && source.type.kind == voidType))
3276 else if((dest.kind == pointerType || dest.kind == arrayType) &&
3277 (source.kind == arrayType || source.kind == pointerType))
3279 if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
3286 static void FreeConvert(Conversion convert)
3288 if(convert.resultType)
3289 FreeType(convert.resultType);
3292 bool MatchWithEnums_NameSpace(NameSpace nameSpace, Expression sourceExp, Type dest,
3293 char * string, OldList conversions)
3297 for(link = (BTNamedLink)nameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
3299 Class _class = link.data;
3300 if(_class.type == enumClass)
3302 OldList converts { };
3304 type.kind = classType;
3307 _class.symbol = FindClass(_class.fullName);
3308 type._class = _class.symbol;
3310 if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
3313 Class enumClass = eSystem_FindClass(privateModule, "enum");
3317 for(baseClass = _class ; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
3319 EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
3320 for(value = e.values.first; value; value = value.next)
3322 if(!strcmp(value.name, string))
3327 FreeExpContents(sourceExp);
3328 FreeType(sourceExp.expType);
3330 sourceExp.isConstant = true;
3331 sourceExp.expType = MkClassType(baseClass.fullName);
3335 sourceExp.type = constantExp;
3336 if(!strcmp(baseClass.dataTypeString, "int"))
3337 sprintf(constant, "%d",value.data);
3339 sprintf(constant, "0x%X",value.data);
3340 sourceExp.constant = CopyString(constant);
3341 //for(;baseClass.base && baseClass.base.type != systemClass; baseClass = baseClass.base);
3344 while(converts.first)
3346 Conversion convert = converts.first;
3347 converts.Remove(convert);
3348 conversions.Add(convert);
3357 converts.Free(FreeConvert);
3361 for(nameSpace = (NameSpace *)nameSpace.nameSpaces.first; nameSpace != null; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
3362 if(MatchWithEnums_NameSpace(nameSpace, sourceExp, dest, string, conversions))
3367 public bool ModuleVisibility(Module searchIn, Module searchFor)
3369 SubModule subModule;
3371 if(searchFor == searchIn)
3374 for(subModule = searchIn.modules.first; subModule; subModule = subModule.next)
3376 if(subModule.importMode == publicAccess || searchIn == searchIn.application)
3378 if(ModuleVisibility(subModule.module, searchFor))
3385 bool MatchWithEnums_Module(Module mainModule, Expression sourceExp, Type dest, char * string, OldList conversions)
3389 if(MatchWithEnums_NameSpace(mainModule.application.systemNameSpace, sourceExp, dest, string, conversions))
3391 if(MatchWithEnums_NameSpace(mainModule.application.privateNameSpace, sourceExp, dest, string, conversions))
3393 if(MatchWithEnums_NameSpace(mainModule.application.publicNameSpace, sourceExp, dest, string, conversions))
3396 for(module = mainModule.application.allModules.first; module; module = module.next)
3398 if(ModuleVisibility(mainModule, module) && MatchWithEnums_NameSpace(module.publicNameSpace, sourceExp, dest, string, conversions))
3404 bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
3406 Type source = sourceExp.expType;
3407 Type realDest = dest;
3409 if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
3412 if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
3414 if(source._class && source._class.registered && source._class.registered.type == unitClass)
3416 Class sourceBase, destBase;
3417 for(sourceBase = source._class.registered;
3418 sourceBase && sourceBase.base && sourceBase.base.type != systemClass;
3419 sourceBase = sourceBase.base);
3420 for(destBase = dest._class.registered;
3421 destBase && destBase.base && destBase.base.type != systemClass;
3422 destBase = destBase.base);
3423 //if(source._class.registered == dest._class.registered)
3424 if(sourceBase == destBase)
3433 int64 value = MAXINT;
3438 if(sourceExp.type == constantExp)
3441 value = strtoll(sourceExp.constant, null, 0);
3443 value = strtoull(sourceExp.constant, null, 0);
3445 else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
3448 value = -strtoll(sourceExp.op.exp2.constant, null, 0);
3450 value = -strtoull(sourceExp.op.exp2.constant, null, 0);
3453 if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
3454 !strcmp(source._class.registered.fullName, "ecere::com::unichar"))
3457 source = Type { kind = intType, isSigned = false, refCount = 1 };
3460 if(dest.kind == classType)
3462 Class _class = dest._class ? dest._class.registered : null;
3464 if(_class && _class.type == unitClass)
3466 if(source.kind != classType)
3469 Type tempDest, tempSource;
3471 for(; _class.base.type != systemClass; _class = _class.base);
3473 tempDest = tempType;
3475 tempType.kind = classType;
3477 _class.symbol = FindClass(_class.fullName);
3479 tempType._class = _class.symbol;
3480 tempType.truth = dest.truth;
3482 MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3484 FreeType(sourceExp.expType);
3485 sourceExp.expType = dest; dest.refCount++;
3487 //sourceExp.expType = MkClassType(_class.fullName);
3495 // Why wasn't there something like this?
3496 if(_class && _class.type == bitClass && source.kind != classType)
3498 if(!dest._class.registered.dataType)
3499 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3500 if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
3503 FreeType(sourceExp.expType);
3504 source = sourceExp.expType = MkClassType(dest._class.string);
3507 //source.kind = classType;
3508 //source._class = dest._class;
3512 // Adding two enumerations
3514 if(_class && _class.type == enumClass && source.kind == classType && source._class && source._class.registered && source._class.registered.type == enumClass)
3516 if(!source._class.registered.dataType)
3517 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3518 if(!dest._class.registered.dataType)
3519 dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
3521 if(MatchTypes(source._class.registered.dataType, dest._class.registered.dataType, conversions, null, null, true, false, false))
3524 source = sourceExp.expType = MkClassType(dest._class.string);
3527 //source.kind = classType;
3528 //source._class = dest._class;
3532 if(_class && !strcmp(_class.fullName, "ecere::com::Class") && source.kind == pointerType && source.type && source.type.kind == charType && sourceExp.type == stringExp)
3534 OldList * specs = MkList();
3538 ReadString(string, sourceExp.string);
3539 decl = SpecDeclFromString(string, specs, null);
3541 FreeExpContents(sourceExp);
3542 FreeType(sourceExp.expType);
3544 sourceExp.type = classExp;
3545 sourceExp._classExp.specifiers = specs;
3546 sourceExp._classExp.decl = decl;
3547 sourceExp.expType = dest;
3555 else if(source.kind == classType)
3557 Class _class = source._class ? source._class.registered : null;
3559 if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass )) // TOCHECK: enumClass, bitClass is new here...
3562 if(dest.kind != classType)
3564 // Testing this simpler piece of code... (Broke Units Conversion to no unit Logic)
3565 if(!source._class.registered.dataType)
3566 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3569 dest = MkClassType(source._class.string);
3570 //if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, false, false))
3571 // dest = MkClassType(source._class.string);
3575 if(dest.kind != classType)
3578 Type tempDest, tempSource;
3580 if(!source._class.registered.dataType)
3581 source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
3583 for(; _class.base.type != systemClass; _class = _class.base);
3585 tempSource = tempType;
3586 tempType.kind = classType;
3587 tempType._class = FindClass(_class.fullName);
3588 tempType.truth = source.truth;
3589 tempType.classObjectType = source.classObjectType;
3592 MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
3594 // PUT THIS BACK TESTING UNITS?
3595 if(conversions.last)
3597 ((Conversion)(conversions.last)).resultType = dest;
3601 FreeType(sourceExp.expType);
3602 sourceExp.expType = MkClassType(_class.fullName);
3603 sourceExp.expType.truth = source.truth;
3604 sourceExp.expType.classObjectType = source.classObjectType;
3606 // *** This if was commented out, put it back because "int a =^ Destroy()" shows up bool enum values in autocomplete ***
3608 if(!sourceExp.destType)
3610 FreeType(sourceExp.destType);
3611 sourceExp.destType = sourceExp.expType;
3612 if(sourceExp.expType)
3613 sourceExp.expType.refCount++;
3616 //source = _class.dataType;
3619 // TOCHECK: TESTING THIS NEW CODE
3620 if(!_class.dataType)
3621 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3623 dest = MkClassType(source._class.string);
3624 dest.truth = source.truth;
3625 dest.classObjectType = source.classObjectType;
3628 source = _class.dataType;
3638 if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
3648 if(source.kind == classType)
3650 Class _class = source._class.registered;
3651 if(_class.type == unitClass)
3653 if(!_class.dataType)
3654 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3655 source = _class.dataType;
3659 if(dest.kind == classType)
3661 Class _class = dest._class ? dest._class.registered : null;
3662 if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") ||
3663 (/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass)) // TOCHECK: enumClass, bitClass is new here...
3665 if(_class.type == normalClass || _class.type == noHeadClass)
3667 Expression newExp { };
3668 *newExp = *sourceExp;
3669 if(sourceExp.destType) sourceExp.destType.refCount++;
3670 if(sourceExp.expType) sourceExp.expType.refCount++;
3671 sourceExp.type = castExp;
3672 sourceExp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, null), null));
3673 sourceExp.cast.exp = newExp;
3674 FreeType(sourceExp.expType);
3675 sourceExp.expType = null;
3676 ProcessExpressionType(sourceExp);
3678 // In Debugger, this helps with addresses (e.g. null pointers) that end up casted to a void *: keeps a classType instead of a pointerType
3681 FreeType(sourceExp.expType);
3682 sourceExp.expType = dest;
3686 if(inCompiler) FreeType(dest);
3691 if(!_class.dataType)
3692 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
3694 dest = _class.dataType;
3698 // Accept lower precision types for units, since we want to keep the unit type
3699 if(dest.kind == doubleType &&
3700 (source.kind == doubleType || source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType ||
3701 source.kind == charType))
3703 specs = MkListOne(MkSpecifier(DOUBLE));
3705 else if(dest.kind == floatType &&
3706 (source.kind == floatType || dest.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3707 source.kind == doubleType))
3709 specs = MkListOne(MkSpecifier(FLOAT));
3711 else if(dest.kind == int64Type && (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType ||
3712 source.kind == floatType || source.kind == doubleType))
3715 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3716 ListAdd(specs, MkSpecifier(INT64));
3718 else if(dest.kind == intType && (source.kind == intType || source.kind == shortType || source.kind == charType ||
3719 source.kind == floatType || source.kind == doubleType))
3722 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3723 ListAdd(specs, MkSpecifier(INT));
3725 else if(dest.kind == shortType && (source.kind == shortType || source.kind == charType || source.kind == intType ||
3726 source.kind == floatType || source.kind == doubleType))
3729 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3730 ListAdd(specs, MkSpecifier(SHORT));
3732 else if(dest.kind == charType && (source.kind == charType || source.kind == shortType || source.kind == intType ||
3733 source.kind == floatType || source.kind == doubleType))
3736 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3737 ListAdd(specs, MkSpecifier(CHAR));
3746 else if(dest.kind == doubleType &&
3747 (source.kind == doubleType || source.kind == floatType || source.kind == int64Type || source.kind == intType || source.kind == enumType || source.kind == shortType ||
3748 source.kind == charType))
3750 specs = MkListOne(MkSpecifier(DOUBLE));
3752 else if(dest.kind == floatType &&
3753 (source.kind == floatType || source.kind == enumType || source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3755 specs = MkListOne(MkSpecifier(FLOAT));
3757 else if(dest.kind == charType && (source.kind == charType || source.kind == enumType || source.kind == shortType || source.kind == intType) &&
3758 (dest.isSigned ? (value >= -128 && value <= 127) : (value >= 0 && value <= 255)))
3761 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3762 ListAdd(specs, MkSpecifier(CHAR));
3764 else if(dest.kind == shortType && (source.kind == enumType || source.kind == charType || source.kind == shortType ||
3765 (source.kind == intType && (dest.isSigned ? (value >= -32768 && value <= 32767) : (value >= 0 && value <= 65535)))))
3768 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3769 ListAdd(specs, MkSpecifier(SHORT));
3771 else if(dest.kind == intType && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType))
3774 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3775 ListAdd(specs, MkSpecifier(INT));
3777 else if(dest.kind == int64Type && (source.kind == enumType || source.kind == shortType || source.kind == charType || source.kind == intType || source.kind == int64Type))
3780 if(!dest.isSigned) ListAdd(specs, MkSpecifier(UNSIGNED));
3781 ListAdd(specs, MkSpecifier(INT64));
3783 else if(dest.kind == enumType &&
3784 (source.kind == int64Type || source.kind == intType || source.kind == shortType || source.kind == charType))
3786 specs = MkListOne(MkEnum(MkIdentifier(dest.enumName), null));
3797 Expression newExp { };
3798 *newExp = *sourceExp;
3801 if(sourceExp.destType) sourceExp.destType.refCount++;
3802 if(sourceExp.expType) sourceExp.expType.refCount++;
3804 sourceExp.type = castExp;
3805 if(realDest.kind == classType)
3807 sourceExp.cast.typeName = QMkClass(realDest._class.string, null);
3808 FreeList(specs, FreeSpecifier);
3811 sourceExp.cast.typeName = MkTypeName(specs, null);
3812 if(newExp.type == opExp)
3814 sourceExp.cast.exp = MkExpBrackets(MkListOne(newExp));
3817 sourceExp.cast.exp = newExp;
3819 FreeType(sourceExp.expType);
3820 sourceExp.expType = null;
3821 ProcessExpressionType(sourceExp);
3824 FreeList(specs, FreeSpecifier);
3832 while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
3833 if(sourceExp.type == identifierExp)
3835 Identifier id = sourceExp.identifier;
3836 if(dest.kind == classType)
3838 if(dest._class && dest._class.registered && dest._class.registered.type == enumClass)
3840 Class _class = dest._class.registered;
3841 Class enumClass = eSystem_FindClass(privateModule, "enum");
3844 for( ; _class && _class.type == ClassType::enumClass; _class = _class.base)
3847 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
3848 for(value = e.values.first; value; value = value.next)
3850 if(!strcmp(value.name, id.string))
3855 FreeExpContents(sourceExp);
3856 FreeType(sourceExp.expType);
3858 sourceExp.isConstant = true;
3859 sourceExp.expType = MkClassType(_class.fullName);
3863 sourceExp.type = constantExp;
3864 if(/*_class && */_class.dataTypeString && !strcmp(_class.dataTypeString, "int")) // _class cannot be null here!
3865 sprintf(constant, "%d",value.data);
3867 sprintf(constant, "0x%X",value.data);
3868 sourceExp.constant = CopyString(constant);
3869 //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
3878 // Loop through all enum classes
3879 if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
3886 #define TERTIARY(o, name, m, t, p) \
3887 static bool name(Expression exp, Operand op1, Operand op2, Operand op3) \
3889 exp.type = constantExp; \
3890 exp.string = p(op1.m ? op2.m : op3.m); \
3892 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3896 #define BINARY(o, name, m, t, p) \
3897 static bool name(Expression exp, Operand op1, Operand op2) \
3900 exp.type = constantExp; \
3901 exp.string = p(op1.m o value2); \
3903 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3907 #define BINARY_DIVIDE(o, name, m, t, p) \
3908 static bool name(Expression exp, Operand op1, Operand op2) \
3911 exp.type = constantExp; \
3912 exp.string = p(value2 ? (op1.m o value2) : 0); \
3914 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3918 #define UNARY(o, name, m, t, p) \
3919 static bool name(Expression exp, Operand op1) \
3921 exp.type = constantExp; \
3922 exp.string = p(o op1.m); \
3924 { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
3928 #define OPERATOR_ALL(macro, o, name) \
3929 macro(o, Int##name, i, int, PrintInt) \
3930 macro(o, UInt##name, ui, unsigned int, PrintUInt) \
3931 macro(o, Short##name, s, short, PrintShort) \
3932 macro(o, UShort##name, us, unsigned short, PrintUShort) \
3933 macro(o, Char##name, c, char, PrintChar) \
3934 macro(o, UChar##name, uc, unsigned char, PrintUChar) \
3935 macro(o, Float##name, f, float, PrintFloat) \
3936 macro(o, Double##name, d, double, PrintDouble)
3938 #define OPERATOR_INTTYPES(macro, o, name) \
3939 macro(o, Int##name, i, int, PrintInt) \
3940 macro(o, UInt##name, ui, unsigned int, PrintUInt) \
3941 macro(o, Short##name, s, short, PrintShort) \
3942 macro(o, UShort##name, us, unsigned short, PrintUShort) \
3943 macro(o, Char##name, c, char, PrintChar) \
3944 macro(o, UChar##name, uc, unsigned char, PrintUChar)
3947 // binary arithmetic
3948 OPERATOR_ALL(BINARY, +, Add)
3949 OPERATOR_ALL(BINARY, -, Sub)
3950 OPERATOR_ALL(BINARY, *, Mul)
3951 OPERATOR_ALL(BINARY_DIVIDE, /, Div)
3952 OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
3955 OPERATOR_ALL(UNARY, -, Neg)
3957 // unary arithmetic increment and decrement
3958 OPERATOR_ALL(UNARY, ++, Inc)
3959 OPERATOR_ALL(UNARY, --, Dec)
3961 // binary arithmetic assignment
3962 OPERATOR_ALL(BINARY, =, Asign)
3963 OPERATOR_ALL(BINARY, +=, AddAsign)
3964 OPERATOR_ALL(BINARY, -=, SubAsign)
3965 OPERATOR_ALL(BINARY, *=, MulAsign)
3966 OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
3967 OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
3970 OPERATOR_INTTYPES(BINARY, &, BitAnd)
3971 OPERATOR_INTTYPES(BINARY, |, BitOr)
3972 OPERATOR_INTTYPES(BINARY, ^, BitXor)
3973 OPERATOR_INTTYPES(BINARY, <<, LShift)
3974 OPERATOR_INTTYPES(BINARY, >>, RShift)
3977 OPERATOR_INTTYPES(UNARY, ~, BitNot)
3979 // binary bitwise assignment
3980 OPERATOR_INTTYPES(BINARY, &=, AndAsign)
3981 OPERATOR_INTTYPES(BINARY, |=, OrAsign)
3982 OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
3983 OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
3984 OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
3986 // unary logical negation
3987 OPERATOR_INTTYPES(UNARY, !, Not)
3989 // binary logical equality
3990 OPERATOR_ALL(BINARY, ==, Equ)
3991 OPERATOR_ALL(BINARY, !=, Nqu)
3994 OPERATOR_ALL(BINARY, &&, And)
3995 OPERATOR_ALL(BINARY, ||, Or)
3997 // binary logical relational
3998 OPERATOR_ALL(BINARY, >, Grt)
3999 OPERATOR_ALL(BINARY, <, Sma)
4000 OPERATOR_ALL(BINARY, >=, GrtEqu)
4001 OPERATOR_ALL(BINARY, <=, SmaEqu)
4003 // tertiary condition operator
4004 OPERATOR_ALL(TERTIARY, ?, Cond)
4006 //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
4007 #define OPERATOR_TABLE_ALL(name, type) \
4008 OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, type##Mod, \
4010 type##Inc, type##Dec, \
4011 type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, type##ModAsign, \
4012 type##BitAnd, type##BitOr, type##BitXor, type##LShift, type##RShift, \
4014 type##AndAsign, type##OrAsign, type##XorAsign, type##LShiftAsign, type##RShiftAsign, \
4016 type##Equ, type##Nqu, \
4017 type##And, type##Or, \
4018 type##Grt, type##Sma, type##GrtEqu, type##SmaEqu, type##Cond \
4021 #define OPERATOR_TABLE_INTTYPES(name, type) \
4022 OpTable name##Ops = { type##Add, type##Sub, type##Mul, type##Div, null, \
4024 type##Inc, type##Dec, \
4025 type##Asign, type##AddAsign, type##SubAsign, type##MulAsign, type##DivAsign, null, \
4026 null, null, null, null, null, \
4028 null, null, null, null, null, \
4030 type##Equ, type##Nqu, \
4031 type##And, type##Or, \
4032 type##Grt, type##Sma, type##GrtEqu, type##SmaEqu \
4035 OPERATOR_TABLE_ALL(int, Int)
4036 OPERATOR_TABLE_ALL(uint, UInt)
4037 OPERATOR_TABLE_ALL(short, Short)
4038 OPERATOR_TABLE_ALL(ushort, UShort)
4039 OPERATOR_TABLE_INTTYPES(float, Float)
4040 OPERATOR_TABLE_INTTYPES(double, Double)
4041 OPERATOR_TABLE_ALL(char, Char)
4042 OPERATOR_TABLE_ALL(uchar, UChar)
4044 //OpTable intOps = { IntAdd, IntSub, IntMul, IntDiv, IntMod, IntExp, IntNot, IntBwn, IntOr, IntAnd, IntEqu, IntNqu, IntGrt, IntSma, IntGrtEqu, IntSmaEqu, IntNeg, IntLBitSft, IntRBitSft };
4045 //OpTable uintOps = { UIntAdd, UIntSub, UIntMul, UIntDiv, UIntMod, UIntExp, UIntNot, UIntBwn, UIntOr, UIntAnd, UIntEqu, UIntNqu, UIntGrt, UIntSma, UIntGrtEqu, UIntSmaEqu, UIntNeg, UIntLBitSft, UIntRBitSft };
4046 //OpTable shortOps = { ShortAdd, ShortSub, ShortMul, ShortDiv, ShortMod, ShortExp, ShortNot, ShortBwn, ShortOr, ShortAnd, ShortEqu, ShortNqu, ShortGrt, ShortSma, ShortGrtEqu, ShortSmaEqu, ShortNeg, ShortLBitSft, ShortRBitSft };
4047 //OpTable ushortOps = { UShortAdd, UShortSub, UShortMul, UShortDiv, UShortMod, UShortExp, UShortNot, UShortBwn, UShortOr, UShortAnd, UShortEqu, UShortNqu, UShortGrt, UShortSma, UShortGrtEqu, UShortSmaEqu, UShortNeg, UShortLBitSft, UShortRBitSft };
4048 //OpTable floatOps = { FloatAdd, FloatSub, FloatMul, FloatDiv, null, null, null, null, null, null, FloatEqu, FloatNqu, FloatGrt, FloatSma, FloatGrtEqu, FloatSmaEqu, FloatNeg, null, null };
4049 //OpTable doubleOps = { DoubleAdd, DoubleSub, DoubleMul, DoubleDiv, null, null, null, null, null, null, DoubleEqu, DoubleNqu, DoubleGrt, DoubleSma, DoubleGrtEqu, DoubleSmaEqu, DoubleNeg, null, null };
4050 //OpTable charOps = { CharAdd, CharSub, CharMul, CharDiv, CharMod, CharExp, CharNot, CharBwn, CharOr, CharAnd, CharEqu, CharNqu, CharGrt, CharSma, CharGrtEqu, CharSmaEqu, CharNeg, CharLBitSft, CharRBitSft };
4051 //OpTable ucharOps = { UCharAdd, UCharSub, UCharMul, UCharDiv, UCharMod, UCharExp, UCharNot, UCharBwn, UCharOr, UCharAnd, UCharEqu, UCharNqu, UCharGrt, UCharSma, UCharGrtEqu, UCharSmaEqu, UCharNeg, UCharLBitSft, UCharRBitSft };
4053 public void ReadString(char * output, char * string)
4055 int len = strlen(string);
4057 bool quoted = false, escaped = false;
4058 for(c = 0; c<len; c++)
4060 char ch = string[c];
4065 case 'n': output[d] = '\n'; break;
4066 case 't': output[d] = '\t'; break;
4067 case 'a': output[d] = '\a'; break;
4068 case 'b': output[d] = '\b'; break;
4069 case 'f': output[d] = '\f'; break;
4070 case 'r': output[d] = '\r'; break;
4071 case 'v': output[d] = '\v'; break;
4072 case '\\': output[d] = '\\'; break;
4073 case '\"': output[d] = '\"'; break;
4074 default: output[d++] = '\\'; output[d] = ch;
4075 //default: output[d] = ch;
4096 public Operand GetOperand(Expression exp)
4099 Type type = exp.expType;
4102 while(type.kind == classType &&
4103 type._class.registered && (type._class.registered.type == bitClass || type._class.registered.type == unitClass || type._class.registered.type == enumClass))
4105 if(!type._class.registered.dataType)
4106 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4107 type = type._class.registered.dataType;
4110 op.kind = type.kind;
4111 op.type = exp.expType;
4112 if(exp.isConstant && exp.type == constantExp)
4118 if(exp.constant[0] == '\'')
4119 op.c = exp.constant[1];
4120 else if(type.isSigned)
4122 op.c = (char)strtol(exp.constant, null, 0);
4127 op.uc = (unsigned char)strtoul(exp.constant, null, 0);
4135 op.s = (short)strtol(exp.constant, null, 0);
4140 op.us = (unsigned short)strtoul(exp.constant, null, 0);
4148 op.i = (int)strtol(exp.constant, null, 0);
4153 op.ui = (unsigned int)strtoul(exp.constant, null, 0);
4161 op.i64 = (int64)_strtoi64(exp.constant, null, 0);
4166 op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
4174 op.i64 = (int64)_strtoi64(exp.constant, null, 0);
4179 op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
4185 op.f = (float)strtod(exp.constant, null);
4189 op.d = (double)strtod(exp.constant, null);
4192 //case classType: For when we have operator overloading...
4193 // Pointer additions
4194 //case functionType:
4198 op.ui64 = _strtoui64(exp.constant, null, 0);
4199 op.kind = pointerType;
4209 static void UnusedFunction()
4212 a.OnGetString(0,0,0);
4215 extern int __ecereVMethodID_class_OnGetString;
4218 static void PopulateInstanceProcessMember(Instantiation inst, OldList * memberList, DataMember parentDataMember, uint offset)
4220 DataMember dataMember;
4221 for(dataMember = parentDataMember.members.first; dataMember; dataMember = dataMember.next)
4223 if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4224 PopulateInstanceProcessMember(inst, memberList, dataMember, offset + dataMember.offset);
4228 MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4230 void * ptr = inst.data + dataMember.offset + offset;
4231 char * result = null;
4232 exp.loc = member.loc = inst.loc;
4233 ((Identifier)member.identifiers->first).loc = inst.loc;
4235 if(!dataMember.dataType)
4236 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4237 type = dataMember.dataType;
4238 if(type.kind == classType)
4240 Class _class = type._class.registered;
4241 if(_class.type == enumClass)
4243 Class enumClass = eSystem_FindClass(privateModule, "enum");
4246 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4248 for(item = e.values.first; item; item = item.next)
4250 if((int)item.data == *(int *)ptr)
4258 exp.identifier = MkIdentifier(result);
4259 exp.type = identifierExp;
4260 exp.destType = MkClassType(_class.fullName);
4261 ProcessExpressionType(exp);
4265 if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4267 if(!_class.dataType)
4268 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4269 type = _class.dataType;
4278 FreeExpContents(exp);
4280 exp.constant = PrintFloat(*(float*)ptr);
4281 exp.type = constantExp;
4286 FreeExpContents(exp);
4288 exp.constant = PrintDouble(*(double*)ptr);
4289 exp.type = constantExp;
4294 FreeExpContents(exp);
4296 exp.constant = PrintInt(*(int*)ptr);
4297 exp.type = constantExp;
4302 FreeExpContents(exp);
4304 exp.constant = PrintInt64(*(int64*)ptr);
4305 exp.type = constantExp;
4310 FreeExpContents(exp);
4312 exp.constant = PrintInt64((int64)*(intptr*)ptr);
4313 exp.type = constantExp;
4317 Compiler_Error($"Unhandled type populating instance\n");
4320 ListAdd(memberList, member);
4323 if(parentDataMember.type == unionMember)
4328 void PopulateInstance(Instantiation inst)
4330 Symbol classSym = inst._class.symbol; // FindClass(inst._class.name);
4331 Class _class = classSym.registered;
4332 DataMember dataMember;
4333 OldList * memberList = MkList();
4334 inst.members = MkListOne(MkMembersInitList(memberList));
4335 for(dataMember = _class.membersAndProperties.first; dataMember; dataMember = dataMember.next)
4337 if(!dataMember.isProperty)
4339 if(!dataMember.name && (dataMember.type == structMember || dataMember.type == unionMember))
4340 PopulateInstanceProcessMember(inst, memberList, dataMember, dataMember.offset);
4344 MemberInit member = MkMemberInit(MkListOne(MkIdentifier(dataMember.name)), MkInitializerAssignment(exp));
4346 void * ptr = inst.data + dataMember.offset;
4347 char * result = null;
4349 exp.loc = member.loc = inst.loc;
4350 ((Identifier)member.identifiers->first).loc = inst.loc;
4352 if(!dataMember.dataType)
4353 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4354 type = dataMember.dataType;
4355 if(type.kind == classType)
4357 Class _class = type._class.registered;
4358 if(_class.type == enumClass)
4360 Class enumClass = eSystem_FindClass(privateModule, "enum");
4363 EnumClassData e = ACCESS_CLASSDATA(_class, enumClass);
4365 for(item = e.values.first; item; item = item.next)
4367 if((int)item.data == *(int *)ptr)
4376 exp.identifier = MkIdentifier(result);
4377 exp.type = identifierExp;
4378 exp.destType = MkClassType(_class.fullName);
4379 ProcessExpressionType(exp);
4382 if(_class.type == enumClass || _class.type == unitClass || _class.type == bitClass)
4384 if(!_class.dataType)
4385 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4386 type = _class.dataType;
4395 exp.constant = PrintFloat(*(float*)ptr);
4396 exp.type = constantExp;
4401 exp.constant = PrintDouble(*(double*)ptr);
4402 exp.type = constantExp;
4407 exp.constant = PrintInt(*(int*)ptr);
4408 exp.type = constantExp;
4413 exp.constant = PrintInt64(*(int64*)ptr);
4414 exp.type = constantExp;
4419 exp.constant = PrintInt64((int64)*(intptr*)ptr);
4420 exp.type = constantExp;
4424 Compiler_Error($"Unhandled type populating instance\n");
4427 ListAdd(memberList, member);
4433 void ComputeInstantiation(Expression exp)
4435 Instantiation inst = exp.instance;
4436 MembersInit members;
4437 Symbol classSym = inst._class ? inst._class.symbol : null; // FindClass(inst._class.name);
4438 Class _class = classSym ? classSym.registered : null;
4439 DataMember curMember = null;
4440 Class curClass = null;
4441 DataMember subMemberStack[256];
4442 int subMemberStackPos = 0;
4445 if(_class && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass ))
4447 // Don't recompute the instantiation...
4448 // Non Simple classes will have become constants by now
4452 if(_class.type == normalClass || _class.type == noHeadClass)
4453 inst.data = (byte *)eInstance_New(_class);
4455 inst.data = new0 byte[_class.structSize];
4460 for(members = inst.members->first; members; members = members.next)
4462 switch(members.type)
4464 case dataMembersInit:
4466 if(members.dataMembers)
4469 for(member = members.dataMembers->first; member; member = member.next)
4471 Identifier ident = member.identifiers ? member.identifiers->first : null;
4474 Property prop = null;
4475 DataMember dataMember = null;
4476 Method method = null;
4477 uint dataMemberOffset;
4481 eClass_FindNextMember(_class, &curClass, &curMember, subMemberStack, &subMemberStackPos);
4484 if(curMember.isProperty)
4485 prop = (Property)curMember;
4488 dataMember = curMember;
4490 // CHANGED THIS HERE
4491 eClass_FindDataMemberAndOffset(_class, dataMember.name, &dataMemberOffset, privateModule, null, null);
4492 // dataMemberOffset = dataMember.offset;
4499 prop = eClass_FindProperty(_class, ident.string, privateModule);
4503 if(prop.memberAccess == publicAccess)
4505 curMember = (DataMember)prop;
4506 curClass = prop._class;
4511 DataMember _subMemberStack[256];
4512 int _subMemberStackPos = 0;
4514 // FILL MEMBER STACK
4515 dataMember = eClass_FindDataMemberAndOffset(_class, ident.string, &dataMemberOffset, privateModule, _subMemberStack, &_subMemberStackPos);
4520 if(dataMember.memberAccess == publicAccess)
4522 curMember = dataMember;
4523 curClass = dataMember._class;
4524 memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
4525 subMemberStackPos = _subMemberStackPos;
4531 if(found && member.initializer && member.initializer.type == expInitializer)
4533 Expression value = member.initializer.exp;
4537 type = prop.dataType;
4541 if(!dataMember.dataType)
4542 dataMember.dataType = ProcessTypeString(dataMember.dataTypeString, false);
4544 type = dataMember.dataType;
4547 if(ident && ident.next)
4549 // for(; ident && type; ident = ident.next)
4550 for(ident = ident.next; ident && type; ident = ident.next)
4552 if(type.kind == classType)
4554 prop = eClass_FindProperty(type._class.registered,
4555 ident.string, privateModule);
4557 type = prop.dataType;
4560 dataMember = eClass_FindDataMemberAndOffset(type._class.registered,
4561 ident.string, &dataMemberOffset, privateModule, null, null);
4563 type = dataMember.dataType;
4566 else if(type.kind == structType || type.kind == unionType)
4569 for(memberType = type.members.first; memberType; memberType = memberType.next)
4571 if(!strcmp(memberType.name, ident.string))
4582 FreeType(value.destType);
4583 value.destType = type;
4584 if(type) type.refCount++;
4585 ComputeExpression(value);
4587 if(value && (_class.type == structClass || _class.type == normalClass || _class.type == noHeadClass /*&& value.expType.kind == type.kind*/))
4589 if(type.kind == classType)
4591 Class _class = type._class.registered;
4592 if(_class.type == bitClass || _class.type == unitClass ||
4593 _class.type == enumClass)
4595 if(!_class.dataType)
4596 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4597 type = _class.dataType;
4603 void * ptr = inst.data + dataMemberOffset;
4605 if(value.type == constantExp)
4611 GetInt(value, (int*)ptr);
4616 GetInt64(value, (int64*)ptr);
4621 GetIntPtr(value, (intptr*)ptr);
4626 GetFloat(value, (float*)ptr);
4631 GetDouble(value, (double *)ptr);
4636 else if(value.type == instanceExp)
4638 if(type.kind == classType)
4640 Class _class = type._class.registered;
4641 if(_class.type == structClass)
4643 ComputeTypeSize(type);
4644 if(value.instance.data)
4645 memcpy(ptr, value.instance.data, type.size);
4652 if(value.type == instanceExp && value.instance.data)
4654 void (*Set)(void *, void *) = (void *)prop.Set;
4655 Set(inst.data, value.instance.data);
4656 PopulateInstance(inst);
4658 else if(value.type == constantExp)
4664 void (*Set)(void *, double) = (void *)prop.Set;
4665 Set(inst.data, strtod(value.constant, null) );
4670 void (*Set)(void *, float) = (void *)prop.Set;
4671 Set(inst.data, (float)(strtod(value.constant, null)));
4676 void (*Set)(void *, int) = (void *)prop.Set;
4677 Set(inst.data, strtol(value.constant, null, 0));
4682 void (*Set)(void *, int64) = (void *)prop.Set;
4683 Set(inst.data, _strtoi64(value.constant, null, 0));
4688 void (*Set)(void *, intptr) = (void *)prop.Set;
4689 Set(inst.data, (intptr)_strtoi64(value.constant, null, 0));
4694 else if(value.type == stringExp)
4697 ReadString(temp, value.string);
4698 ((void (*)(void *, void *))(void *)prop.Set)(inst.data, temp);
4702 else if(_class.type == unitClass)
4706 // Only support converting units to units for now...
4707 if(value.type == constantExp)
4709 if(type.kind == classType)
4711 Class _class = type._class.registered;
4712 if(_class.type == unitClass)
4714 if(!_class.dataType)
4715 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
4716 type = _class.dataType;
4719 // TODO: Assuming same base type for units...
4725 float (*Set)(float) = (void *)prop.Set;
4726 GetFloat(member.initializer.exp, &fValue);
4727 exp.constant = PrintFloat(Set(fValue));
4728 exp.type = constantExp;
4734 double (*Set)(double) = (void *)prop.Set;
4735 GetDouble(member.initializer.exp, &dValue);
4736 exp.constant = PrintDouble(Set(dValue));
4737 exp.type = constantExp;
4744 else if(_class.type == bitClass)
4748 if(value.type == instanceExp && value.instance.data)
4750 unsigned int (*Set)(void *) = (void *)prop.Set;
4751 bits = Set(value.instance.data);
4753 else if(value.type == constantExp)
4759 BitMember bitMember = (BitMember) dataMember;
4762 GetInt(value, &part);
4763 bits = (bits & ~bitMember.mask);
4764 if(!bitMember.dataType)
4765 bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
4767 type = bitMember.dataType;
4769 if(type.kind == classType && type._class && type._class.registered)
4771 if(!type._class.registered.dataType)
4772 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
4773 type = type._class.registered.dataType;
4780 bits |= ((char)part << bitMember.pos);
4782 bits |= ((unsigned char)part << bitMember.pos);
4786 bits |= ((short)part << bitMember.pos);
4788 bits |= ((unsigned short)part << bitMember.pos);
4793 bits |= ((int)part << bitMember.pos);
4795 bits |= ((unsigned int)part << bitMember.pos);
4799 bits |= ((int64)part << bitMember.pos);
4801 bits |= ((uint64)part << bitMember.pos);
4805 bits |= ((intptr)part << bitMember.pos);
4807 bits |= ((uintptr)part << bitMember.pos);
4815 if(_class && _class.type == unitClass)
4817 ComputeExpression(member.initializer.exp);
4818 exp.constant = member.initializer.exp.constant;
4819 exp.type = constantExp;
4821 member.initializer.exp.constant = null;
4831 if(_class && _class.type == bitClass)
4833 exp.constant = PrintHexUInt(bits);
4834 exp.type = constantExp;
4836 if(exp.type != instanceExp)
4842 void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
4844 if(exp.op.op == SIZEOF)
4846 FreeExpContents(exp);
4847 exp.type = constantExp;
4848 exp.constant = PrintUInt(ComputeTypeSize(op1.type));
4859 // Provide default unary +
4860 Expression exp2 = exp.op.exp2;
4862 FreeExpContents(exp);
4863 FreeType(exp.expType);
4864 FreeType(exp.destType);
4870 if(op1.ops.Neg) { FreeExpContents(exp); op1.ops.Neg(exp, op1); }
4872 // unary arithmetic increment and decrement
4873 //OPERATOR_ALL(UNARY, ++, Inc)
4874 //OPERATOR_ALL(UNARY, --, Dec)
4877 if(op1.ops.BitNot) { FreeExpContents(exp); op1.ops.BitNot(exp, op1); }
4879 // unary logical negation
4881 if(op1.ops.Not) { FreeExpContents(exp); op1.ops.Not(exp, op1); }
4889 // binary arithmetic
4891 if(op1.ops.Add) { FreeExpContents(exp); op1.ops.Add(exp, op1, op2); }
4894 if(op1.ops.Sub) { FreeExpContents(exp); op1.ops.Sub(exp, op1, op2); }
4897 if(op1.ops.Mul) { FreeExpContents(exp); op1.ops.Mul(exp, op1, op2); }
4900 if(op1.ops.Div) { FreeExpContents(exp); op1.ops.Div(exp, op1, op2); }
4903 if(op1.ops.Mod) { FreeExpContents(exp); op1.ops.Mod(exp, op1, op2); }
4905 // binary arithmetic assignment
4906 //OPERATOR_ALL(BINARY, =, Asign)
4907 //OPERATOR_ALL(BINARY, +=, AddAsign)
4908 //OPERATOR_ALL(BINARY, -=, SubAsign)
4909 //OPERATOR_ALL(BINARY, *=, MulAsign)
4910 //OPERATOR_ALL(BINARY, /=, DivAsign)
4911 //OPERATOR_ALL(BINARY, %=, ModAsign)
4916 if(op1.ops.BitAnd) { FreeExpContents(exp); op1.ops.BitAnd(exp, op1, op2); }
4920 if(op1.ops.BitOr) { FreeExpContents(exp); op1.ops.BitOr(exp, op1, op2); }
4923 if(op1.ops.BitXor) { FreeExpContents(exp); op1.ops.BitXor(exp, op1, op2); }
4926 if(op1.ops.LShift) { FreeExpContents(exp); op1.ops.LShift(exp, op1, op2); }
4929 if(op1.ops.RShift) { FreeExpContents(exp); op1.ops.RShift(exp, op1, op2); }
4931 // binary bitwise assignment
4932 //OPERATOR_INTTYPES(BINARY, &=, AndAsign)
4933 //OPERATOR_INTTYPES(BINARY, |=, OrAsign)
4934 //OPERATOR_INTTYPES(BINARY, ^=, XorAsign)
4935 //OPERATOR_INTTYPES(BINARY, <<=, LShiftAsign)
4936 //OPERATOR_INTTYPES(BINARY, >>=, RShiftAsign)
4937 // binary logical equality
4939 if(op1.ops.Equ) { FreeExpContents(exp); op1.ops.Equ(exp, op1, op2); }
4942 if(op1.ops.Nqu) { FreeExpContents(exp); op1.ops.Nqu(exp, op1, op2); }
4946 if(op1.ops.And) { FreeExpContents(exp); op1.ops.And(exp, op1, op2); }
4949 if(op1.ops.Or) { FreeExpContents(exp); op1.ops.Or(exp, op1, op2); }
4951 // binary logical relational
4953 if(op1.ops.Grt) { FreeExpContents(exp); op1.ops.Grt(exp, op1, op2); }
4956 if(op1.ops.Sma) { FreeExpContents(exp); op1.ops.Sma(exp, op1, op2); }
4959 if(op1.ops.GrtEqu) { FreeExpContents(exp); op1.ops.GrtEqu(exp, op1, op2); }
4962 if(op1.ops.SmaEqu) { FreeExpContents(exp); op1.ops.SmaEqu(exp, op1, op2); }
4969 void ComputeExpression(Expression exp)
4971 char expString[10240];
4972 expString[0] = '\0';
4974 PrintExpression(exp, expString);
4981 ComputeInstantiation(exp);
4990 Expression exp1, exp2 = null;
4994 // We don't care about operations with only exp2 (INC_OP, DEC_OP...)
4996 ComputeExpression(exp.op.exp2);
4999 ComputeExpression(exp.op.exp1);
5002 op1 = GetOperand(exp1);
5003 if(op1.type) op1.type.refCount++;
5006 op2 = GetOperand(exp2);
5007 if(op2.type) op2.type.refCount++;
5013 op1 = GetOperand(exp1);
5014 if(op1.type) op1.type.refCount++;
5017 CallOperator(exp, exp1, exp2, op1, op2);
5024 if(exp.op.exp1 && exp.op.exp2)
5029 FreeExpContents(exp);
5030 op1.ops.BitAnd(exp, op1, op2);
5039 FreeExpContents(exp);
5040 op1.ops.Mul(exp, op1, op2);
5049 FreeExpContents(exp);
5050 op1.ops.Add(exp, op1, op2);
5055 // Provide default unary +
5056 Expression exp2 = exp.op.exp2;
5058 FreeExpContents(exp);
5059 FreeType(exp.expType);
5060 FreeType(exp.destType);
5071 FreeExpContents(exp);
5072 op1.ops.Sub(exp, op1, op2);
5079 FreeExpContents(exp);
5080 op1.ops.Neg(exp, op1);
5087 FreeExpContents(exp);
5088 op1.ops.BitNot(exp, op1);
5094 FreeExpContents(exp);
5095 op1.ops.Not(exp, op1);
5098 // Binary only operators
5102 FreeExpContents(exp);
5103 op1.ops.Div(exp, op1, op2);
5109 FreeExpContents(exp);
5110 op1.ops.Mod(exp, op1, op2);
5122 FreeExpContents(exp);
5123 op1.ops.Sma(exp, op1, op2);
5132 FreeExpContents(exp);
5133 op1.ops.Grt(exp, op1, op2);
5142 FreeExpContents(exp);
5143 op1.ops.SmaEqu(exp, op1, op2);
5152 FreeExpContents(exp);
5153 op1.ops.GrtEqu(exp, op1, op2);
5162 FreeExpContents(exp);
5163 op1.ops.Equ(exp, op1, op2);
5172 FreeExpContents(exp);
5173 op1.ops.Nqu(exp, op1, op2);
5180 FreeExpContents(exp);
5181 op1.ops.BitOr(exp, op1, op2);
5187 FreeExpContents(exp);
5188 op1.ops.BitXor(exp, op1, op2);
5196 FreeExpContents(exp);
5197 exp.type = constantExp;
5198 exp.constant = PrintUInt(ComputeTypeSize(op1.type));
5202 if(op1.type) FreeType(op1.type);
5203 if(op2.type) FreeType(op2.type);
5207 case extensionExpressionExp:
5210 for(e = exp.list->first; e; e = n)
5215 OldList * list = exp.list;
5216 ComputeExpression(e);
5217 //FreeExpContents(exp);
5218 FreeType(exp.expType);
5219 FreeType(exp.destType);
5236 exp.isConstant = true;
5238 ComputeExpression(exp.index.exp);
5239 if(!exp.index.exp.isConstant)
5240 exp.isConstant = false;
5242 for(e = exp.index.index->first; e; e = e.next)
5244 ComputeExpression(e);
5247 // Check if this type is int
5250 exp.isConstant = false;
5252 exp.expType = Dereference(exp.index.exp.expType);
5258 Expression memberExp = exp.member.exp;
5259 Identifier memberID = exp.member.member;
5262 ComputeExpression(exp.member.exp);
5263 type = exp.member.exp.expType;
5266 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);
5267 Property prop = null;
5268 DataMember member = null;
5269 Class convertTo = null;
5270 if(type.kind == subClassType && exp.member.exp.type == classExp)
5271 _class = eSystem_FindClass(privateModule, "ecere::com::Class");
5278 PrintType(type, string, false, true);
5279 classSym = FindClass(string);
5280 _class = classSym ? classSym.registered : null;
5283 if(exp.member.member)
5285 prop = eClass_FindProperty(_class, exp.member.member.string, privateModule);
5287 member = eClass_FindDataMember(_class, exp.member.member.string, privateModule, null, null);
5289 if(!prop && !member && _class && exp.member.member)
5291 Symbol classSym = FindClass(exp.member.member.string);
5293 _class = classSym ? classSym.registered : null;
5294 prop = eClass_FindProperty(_class, convertTo.fullName, privateModule);
5301 Type type = prop.dataType;
5302 // TODO: Assuming same base type for units...
5303 if(_class.type == unitClass)
5305 if(type.kind == classType)
5307 Class _class = type._class.registered;
5308 if(_class.type == unitClass)
5310 if(!_class.dataType)
5311 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5312 type = _class.dataType;
5320 float (*Get)(float) = (void *)prop.Get;
5321 GetFloat(exp.member.exp, &value);
5322 exp.constant = PrintFloat(Get ? Get(value) : value);
5323 exp.type = constantExp;
5329 double (*Get)(double);
5330 GetDouble(exp.member.exp, &value);
5333 Get = (void *)prop.Set;
5335 Get = (void *)prop.Get;
5336 exp.constant = PrintDouble(Get ? Get(value) : value);
5337 exp.type = constantExp;
5346 Expression value = exp.member.exp;
5349 ProcessPropertyType(prop);
5351 type = prop.dataType;
5354 // printf("Investigate this\n");
5356 else if(_class.type == structClass)
5362 Class propertyClass = type._class.registered;
5363 if(propertyClass.type == structClass && value.type == instanceExp)
5365 void (*Set)(void *, void *) = (void *)prop.Set;
5366 exp.instance = Instantiation { };
5367 exp.instance.data = new0 byte[_class.structSize];
5368 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5369 exp.instance.loc = exp.loc;
5370 exp.type = instanceExp;
5371 Set(exp.instance.data, value.instance.data);
5372 PopulateInstance(exp.instance);
5379 void (*Set)(void *, int) = (void *)prop.Set;
5381 exp.instance = Instantiation { };
5382 exp.instance.data = new0 byte[_class.structSize];
5383 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5384 exp.instance.loc = exp.loc;
5385 exp.type = instanceExp;
5387 GetInt(value, &intValue);
5389 Set(exp.instance.data, intValue);
5390 PopulateInstance(exp.instance);
5396 void (*Set)(void *, int64) = (void *)prop.Set;
5398 exp.instance = Instantiation { };
5399 exp.instance.data = new0 byte[_class.structSize];
5400 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5401 exp.instance.loc = exp.loc;
5402 exp.type = instanceExp;
5404 GetInt64(value, &intValue);
5406 Set(exp.instance.data, intValue);
5407 PopulateInstance(exp.instance);
5414 void (*Set)(void *, intptr) = (void *)prop.Set;
5416 exp.instance = Instantiation { };
5417 exp.instance.data = new0 byte[_class.structSize];
5418 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5419 exp.instance.loc = exp.loc;
5420 exp.type = instanceExp;
5422 GetIntPtr(value, &intValue);
5424 Set(exp.instance.data, intValue);
5425 PopulateInstance(exp.instance);
5431 void (*Set)(void *, double) = (void *)prop.Set;
5433 exp.instance = Instantiation { };
5434 exp.instance.data = new0 byte[_class.structSize];
5435 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5436 exp.instance.loc = exp.loc;
5437 exp.type = instanceExp;
5439 GetDouble(value, &doubleValue);
5441 Set(exp.instance.data, doubleValue);
5442 PopulateInstance(exp.instance);
5447 else if(_class.type == bitClass)
5453 Class propertyClass = type._class.registered;
5454 if(propertyClass.type == structClass && value.instance.data)
5456 unsigned int (*Set)(void *) = (void *)prop.Set;
5457 unsigned int bits = Set(value.instance.data);
5458 exp.constant = PrintHexUInt(bits);
5459 exp.type = constantExp;
5462 else if(_class.type == bitClass)
5465 unsigned int (*Set)(unsigned int) = (void *)prop.Set;
5468 GetUInt(exp.member.exp, &value);
5470 exp.constant = PrintHexUInt(bits);
5471 exp.type = constantExp;
5479 if(_class.type == bitClass)
5482 GetUInt(exp.member.exp, &value);
5488 Class _class = type._class.registered;
5489 if(_class.type == structClass)
5491 void (*Get)(unsigned int, void *) = (void *)prop.Get;
5493 exp.instance = Instantiation { };
5494 exp.instance.data = new0 byte[_class.structSize];
5495 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5496 exp.instance.loc = exp.loc;
5497 //exp.instance.fullSet = true;
5498 exp.type = instanceExp;
5499 Get(value, exp.instance.data);
5500 PopulateInstance(exp.instance);
5502 else if(_class.type == bitClass)
5504 unsigned int (*Get)(unsigned int) = (void *)prop.Get;
5505 uint64 bits = Get(value);
5506 exp.constant = PrintHexUInt64(bits);
5507 exp.type = constantExp;
5513 else if(_class.type == structClass)
5515 char * value = (exp.member.exp.type == instanceExp ) ? exp.member.exp.instance.data : null;
5520 Class _class = type._class.registered;
5521 if(_class.type == structClass && value)
5523 void (*Get)(void *, void *) = (void *)prop.Get;
5525 exp.instance = Instantiation { };
5526 exp.instance.data = new0 byte[_class.structSize];
5527 exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
5528 exp.instance.loc = exp.loc;
5529 //exp.instance.fullSet = true;
5530 exp.type = instanceExp;
5531 Get(value, exp.instance.data);
5532 PopulateInstance(exp.instance);
5540 char * value = exp.member.exp.instance.data;
5545 Class _class = type._class.registered;
5546 if(_class.type == normalClass)
5548 void *(*Get)(void *) = (void *)prop.Get;
5550 exp.instance = Instantiation { };
5551 exp.instance._class = MkSpecifierName(_class.fullName); //MkClassName(_class.fullName);
5552 exp.type = instanceExp;
5553 exp.instance.data = Get(value, exp.instance.data);
5565 exp.isConstant = false;
5573 if(exp.type != ExpressionType::memberExp)
5575 FreeExpression(memberExp);
5576 FreeIdentifier(memberID);
5582 Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
5583 FreeExpContents(exp);
5584 exp.constant = PrintUInt(ComputeTypeSize(type));
5585 exp.type = constantExp;
5591 Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
5592 if(classSym && classSym.registered)
5594 if(classSym.registered.fixed)
5596 FreeSpecifier(exp._class);
5597 exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
5598 exp.type = constantExp;
5602 char className[1024];
5603 strcpy(className, "__ecereClass_");
5604 FullClassNameCat(className, classSym.string, true);
5605 MangleClassName(className);
5607 FreeExpContents(exp);
5608 exp.type = pointerExp;
5609 exp.member.exp = MkExpIdentifier(MkIdentifier(className));
5610 exp.member.member = MkIdentifier("structSize");
5620 if(exp.type == castExp)
5623 ComputeExpression(exp.cast.exp);
5626 if(e && exp.expType)
5629 type = exp.destType;
5632 if(type.kind == classType)
5634 Class _class = type._class.registered;
5635 if(_class && (_class.type == unitClass || _class.type == bitClass))
5637 if(!_class.dataType)
5638 _class.dataType = ProcessTypeString(_class.dataTypeString, false);
5639 type = _class.dataType;
5650 FreeExpContents(exp);
5651 exp.constant = PrintChar(value);
5652 exp.type = constantExp;
5656 unsigned char value;
5657 GetUChar(e, &value);
5658 FreeExpContents(exp);
5659 exp.constant = PrintUChar(value);
5660 exp.type = constantExp;
5667 GetShort(e, &value);
5668 FreeExpContents(exp);
5669 exp.constant = PrintShort(value);
5670 exp.type = constantExp;
5674 unsigned short value;
5675 GetUShort(e, &value);
5676 FreeExpContents(exp);
5677 exp.constant = PrintUShort(value);
5678 exp.type = constantExp;
5686 FreeExpContents(exp);
5687 exp.constant = PrintInt(value);
5688 exp.type = constantExp;
5694 FreeExpContents(exp);
5695 exp.constant = PrintUInt(value);
5696 exp.type = constantExp;
5703 GetInt64(e, &value);
5704 FreeExpContents(exp);
5705 exp.constant = PrintInt64(value);
5706 exp.type = constantExp;
5711 GetUInt64(e, &value);
5712 FreeExpContents(exp);
5713 exp.constant = PrintUInt64(value);
5714 exp.type = constantExp;
5721 GetIntPtr(e, &value);
5722 FreeExpContents(exp);
5723 exp.constant = PrintInt64((int64)value);
5724 exp.type = constantExp;
5729 GetUIntPtr(e, &value);
5730 FreeExpContents(exp);
5731 exp.constant = PrintUInt64((uint64)value);
5732 exp.type = constantExp;
5738 GetFloat(e, &value);
5739 FreeExpContents(exp);
5740 exp.constant = PrintFloat(value);
5741 exp.type = constantExp;
5747 GetDouble(e, &value);
5748 FreeExpContents(exp);
5749 exp.constant = PrintDouble(value);
5750 exp.type = constantExp;
5764 // Caring only about last expression for now...
5765 ComputeExpression(exp.cond.exp->last);
5766 if(exp.cond.elseExp)
5767 ComputeExpression(exp.cond.elseExp);
5769 ComputeExpression(exp.cond.cond);
5771 op1 = GetOperand(exp.cond.cond);
5772 if(op1.type) op1.type.refCount++;
5773 op2 = GetOperand(exp.cond.exp->last);
5774 if(op2.type) op2.type.refCount++;
5775 op3 = GetOperand(exp.cond.elseExp);
5776 if(op3.type) op3.type.refCount++;
5778 if(op1.ops.Cond) { FreeExpContents(exp); op1.ops.Cond(exp, op1, op2, op3); }
5779 if(op1.type) FreeType(op1.type);
5780 if(op2.type) FreeType(op2.type);
5781 if(op3.type) FreeType(op3.type);
5787 static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
5792 OldList converts { };
5795 if(destType.kind == voidType)
5798 if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
5802 // for(convert = converts.last; convert; convert = convert.prev)
5803 for(convert = converts.first; convert; convert = convert.next)
5805 bool empty = !(convert.isGet ? (void *)convert.convert.Get : (void *)convert.convert.Set);
5808 Expression newExp { };
5809 ClassObjectType objectType = exp.expType ? exp.expType.classObjectType : none;
5811 // TODO: Check this...
5813 newExp.destType = null;
5818 exp.type = memberExp;
5819 exp.addedThis = true;
5820 exp.member.exp = newExp;
5821 FreeType(exp.member.exp.expType);
5823 exp.member.exp.expType = MkClassType(convert.convert._class.fullName);
5824 exp.member.exp.expType.classObjectType = objectType;
5825 exp.member.member = MkIdentifier(convert.convert.dataTypeString);
5826 exp.member.memberType = propertyMember;
5827 exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5828 // TESTING THIS... for (int)degrees
5829 exp.needCast = true;
5830 if(exp.expType) exp.expType.refCount++;
5831 ApplyAnyObjectLogic(exp.member.exp);
5836 /*if(exp.isConstant)
5838 // Color { ColorRGB = [exp] };
5839 exp.type = instanceExp;
5840 exp.instance = MkInstantiation(MkSpecifierName((convert.convert._class.fullName), //MkClassName(convert.convert._class.fullName),
5841 null, MkListOne(MkMembersInitList(MkListOne(MkMemberInit(
5842 MkListOne(MkIdentifier(convert.convert.dataTypeString)), newExp)))));
5846 // If not constant, don't turn it yet into an instantiation
5847 // (Go through the deep members system first)
5848 exp.type = memberExp;
5849 exp.addedThis = true;
5850 exp.member.exp = newExp;
5852 // ADDED THIS HERE TO SOLVE PROPERTY ISSUES WITH NOHEAD CLASSES
5853 if(/*!notByReference && */newExp.expType && newExp.expType.kind == classType && newExp.expType._class && newExp.expType._class.registered &&
5854 newExp.expType._class.registered.type == noHeadClass)
5856 newExp.byReference = true;
5859 FreeType(exp.member.exp.expType);
5860 /*exp.member.exp.expType = convert.convert.dataType;
5861 if(convert.convert.dataType) convert.convert.dataType.refCount++;*/
5862 exp.member.exp.expType = null;
5863 if(convert.convert.dataType)
5865 exp.member.exp.expType = { };
5866 CopyTypeInto(exp.member.exp.expType, convert.convert.dataType);
5867 exp.member.exp.expType.refCount = 1;
5868 exp.member.exp.expType.classObjectType = objectType;
5869 ApplyAnyObjectLogic(exp.member.exp);
5872 exp.member.member = MkIdentifier(convert.convert._class.fullName);
5873 exp.member.memberType = reverseConversionMember;
5874 exp.expType = convert.resultType ? convert.resultType :
5875 MkClassType(convert.convert._class.fullName);
5876 exp.needCast = true;
5877 if(convert.resultType) convert.resultType.refCount++;
5883 FreeType(exp.expType);
5886 exp.expType = convert.resultType ? convert.resultType : convert.convert.dataType;
5887 exp.needCast = true;
5888 if(exp.expType) exp.expType.refCount++;
5892 exp.expType = convert.resultType ? convert.resultType : MkClassType(convert.convert._class.fullName);
5893 exp.needCast = true;
5894 if(convert.resultType)
5895 convert.resultType.refCount++;
5899 if(exp.isConstant && inCompiler)
5900 ComputeExpression(exp);
5902 converts.Free(FreeConvert);
5905 if(!result && exp.expType && converts.count) // TO TEST: Added converts.count here to avoid a double warning with function type
5907 result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
5909 if(!result && exp.expType && exp.destType)
5911 if((exp.destType.kind == classType && exp.expType.kind == pointerType &&
5912 exp.expType.type.kind == classType && exp.expType.type._class == exp.destType._class && exp.destType._class.registered && exp.destType._class.registered.type == structClass) ||
5913 (exp.expType.kind == classType && exp.destType.kind == pointerType &&
5914 exp.destType.type.kind == classType && exp.destType.type._class == exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass))
5918 // if(result) CheckTemplateTypes(exp);
5922 void CheckTemplateTypes(Expression exp)
5924 if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
5926 Expression newExp { };
5930 if(exp.destType) exp.destType.refCount++;
5931 if(exp.expType) exp.expType.refCount++;
5935 switch(exp.expType.kind)
5938 if(exp.destType.classObjectType)
5940 // We need to pass the address, just pass it along (Undo what was done above)
5941 if(exp.destType) exp.destType.refCount--;
5942 if(exp.expType) exp.expType.refCount--;
5947 // If we're looking for value:
5948 // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
5950 OldList * unionDefs = MkList();
5951 OldList * statements = MkList();
5952 context = PushContext();
5953 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
5954 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
5955 specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
5956 exp.type = extensionCompoundExp;
5957 exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
5958 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")), '=', newExp))));
5959 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")))));
5960 exp.compound.compound.context = context;
5961 PopContext(context);
5966 exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
5967 exp.cast.exp = MkExpBrackets(MkListOne(newExp));
5971 else if(exp.expType && exp.expType.passAsTemplate && exp.destType && exp.usage.usageGet && exp.destType.kind != templateType && !exp.destType.passAsTemplate)
5973 Expression newExp { };
5977 if(exp.destType) exp.destType.refCount++;
5978 if(exp.expType) exp.expType.refCount++;
5982 switch(exp.expType.kind)
5985 if(exp.destType.classObjectType)
5987 // We need to pass the address, just pass it along (Undo what was done above)
5988 if(exp.destType) exp.destType.refCount--;
5989 if(exp.expType) exp.expType.refCount--;
5994 // If we're looking for value:
5995 // ({ union { double d; uint64 i; } u; u.i = [newExp]; u.d; })
5997 OldList * unionDefs = MkList();
5998 OldList * statements = MkList();
5999 context = PushContext();
6000 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifier(DOUBLE)), MkListOne(MkDeclaratorIdentifier(MkIdentifier("d"))), null)));
6001 ListAdd(unionDefs, MkClassDefDeclaration(MkStructDeclaration(MkListOne(MkSpecifierName("uint64")), MkListOne(MkDeclaratorIdentifier(MkIdentifier("i"))), null)));
6002 specs = MkListOne(MkStructOrUnion(unionSpecifier, null, unionDefs ));
6003 exp.type = extensionCompoundExp;
6004 exp.compound = MkCompoundStmt(MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internal_union")), null)))),statements);
6005 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("i")), '=', newExp))));
6006 ListAdd(statements, MkExpressionStmt(MkListOne(MkExpMember(MkExpIdentifier(MkIdentifier("__internal_union")), MkIdentifier("d")))));
6007 exp.compound.compound.context = context;
6008 PopContext(context);
6013 if(exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type == structClass)
6015 exp.type = bracketsExp;
6016 exp.list = MkListOne(MkExpOp(null, '*', MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)),
6017 MkDeclaratorPointer(MkPointer(null, null), null)), newExp)));
6018 ProcessExpressionType(exp.list->first);
6023 exp.type = bracketsExp;
6024 exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(exp.expType._class.string)), null), newExp));
6025 newExp.needCast = true;
6026 ProcessExpressionType(exp.list->first);
6032 if(exp.expType.kind == templateType)
6034 Type type = ProcessTemplateParameterType(exp.expType.templateParameter);
6037 FreeType(exp.destType);
6038 FreeType(exp.expType);
6043 if(newExp.type == memberExp && newExp.member.memberType == dataMember)
6048 exp.op.exp2 = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uint64")), MkDeclaratorPointer(MkPointer(null, null), null)),
6049 MkExpBrackets(MkListOne(MkExpOp(null, '&', newExp))));
6053 char typeString[1024];
6055 OldList * specs = MkList();
6056 typeString[0] = '\0';
6057 PrintType(exp.expType, typeString, false, false);
6058 decl = SpecDeclFromString(typeString, specs, null);
6061 //exp.cast.typeName = MkTypeName(MkListOne(MkSpecifierName("uint64")), null);
6062 exp.cast.typeName = MkTypeName(specs, decl);
6063 exp.cast.exp = MkExpBrackets(MkListOne(newExp));
6064 exp.cast.exp.needCast = true;
6071 // TODO: The Symbol tree should be reorganized by namespaces
6073 // - Tree of all symbols within (stored without namespace)
6074 // - Tree of sub-namespaces
6076 static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
6078 int nsLen = strlen(nameSpace);
6080 // Start at the name space prefix
6081 for(symbol = (Symbol)tree.FindPrefix(nameSpace); symbol; symbol = (Symbol)((BTNode)symbol).next)
6083 char * s = symbol.string;
6084 if(!strncmp(s, nameSpace, nsLen))
6086 // This supports e.g. matching ecere::Socket to ecere::net::Socket
6089 for(c = strlen(s)-1; c >= 0; c--)
6094 if(!strcmp(namePart, name))
6096 // TODO: Error on ambiguity
6106 static Symbol FindWithNameSpace(BinaryTree tree, char * name)
6109 char nameSpace[1024];
6111 bool gotColon = false;
6113 nameSpace[0] = '\0';
6114 for(c = strlen(name)-1; c >= 0; c--)
6121 namePart = name+c+1;
6122 while(c >= 0 && name[c] == ':') c--;
6125 // Try an exact match first
6126 Symbol symbol = (Symbol)tree.FindString(name);
6130 // Namespace specified
6131 memcpy(nameSpace, name, c + 1);
6134 return ScanWithNameSpace(tree, nameSpace, namePart);
6138 // Looking for a global symbol, e.g. ::Sleep()
6139 Symbol symbol = (Symbol)tree.FindString(namePart);
6144 // Name only (no namespace specified)
6145 Symbol symbol = (Symbol)tree.FindString(namePart);
6148 return ScanWithNameSpace(tree, "", namePart);
6153 static void ProcessDeclaration(Declaration decl);
6155 /*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
6158 //Time startTime = GetTime();
6160 // Optimize this later? Do this before/less?
6162 Symbol symbol = null;
6163 // First, check if the identifier is declared inside the function
6164 //for(ctx = curContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6166 for(ctx = startContext; ctx /*!= topContext.parent */&& !symbol; ctx = ctx.parent)
6168 if(ctx == globalContext && !globalNameSpace && ctx.hasNameSpace)
6174 strcpy(curName, thisNameSpace);
6175 strcat(curName, "::");
6176 strcat(curName, name);
6177 // Try to resolve in current namespace first
6178 symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, curName);
6181 symbol = FindWithNameSpace(isStruct ? ctx.structSymbols : ctx.symbols, name);
6184 symbol = (Symbol)(isStruct ? ctx.structSymbols : ctx.symbols).FindString(name);
6186 if(symbol || ctx == endContext) break;
6188 if(inCompiler && curExternal && symbol && ctx == globalContext && curExternal.symbol && symbol.id > curExternal.symbol.idCode && symbol.pointerExternal)
6190 if(symbol.pointerExternal.type == functionExternal)
6192 FunctionDefinition function = symbol.pointerExternal.function;
6194 // Modified this recently...
6195 Context tmpContext = curContext;
6197 symbol.pointerExternal = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
6198 curContext = tmpContext;
6200 symbol.pointerExternal.symbol = symbol;
6203 DeclareType(symbol.type, true, true);
6205 ast->Insert(curExternal.prev, symbol.pointerExternal);
6207 symbol.id = curExternal.symbol.idCode;
6210 else if(symbol.pointerExternal.type == declarationExternal && curExternal.symbol.idCode < symbol.pointerExternal.symbol.id) // Added id comparison because Global Function prototypes were broken
6212 ast->Move(symbol.pointerExternal, curExternal.prev);
6213 symbol.id = curExternal.symbol.idCode;
6217 //findSymbolTotalTime += GetTime() - startTime;
6222 static void GetTypeSpecs(Type type, OldList * specs)
6224 if(!type.isSigned && type.kind != intPtrType) ListAdd(specs, MkSpecifier(UNSIGNED));
6229 if(type._class.registered)
6231 if(!type._class.registered.dataType)
6232 type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
6233 GetTypeSpecs(type._class.registered.dataType, specs);
6237 case doubleType: ListAdd(specs, MkSpecifier(DOUBLE)); break;
6238 case floatType: ListAdd(specs, MkSpecifier(FLOAT)); break;
6239 case charType: ListAdd(specs, MkSpecifier(CHAR)); break;
6240 case shortType: ListAdd(specs, MkSpecifier(SHORT)); break;
6241 case int64Type: ListAdd(specs, MkSpecifier(INT64)); break;
6242 case intPtrType: ListAdd(specs, MkSpecifierName(type.isSigned ? "intptr" : "uintptr")); break;
6245 ListAdd(specs, MkSpecifier(INT)); break;
6249 // WARNING : This function expects a null terminated string since it recursively concatenate...
6250 static void _PrintType(Type type, char * string, bool printName, bool printFunction, bool fullName)
6257 if(type._class && type._class.string)
6259 // TODO: typed_object does not fully qualify the type, as it may have taken up an actual class (Stored in _class) from overriding
6260 // look into merging with thisclass ?
6261 if(type.classObjectType == typedObject)
6262 strcat(string, "typed_object");
6264 strcat(string, type._class.string);
6267 if(type._class.registered)
6268 strcat(string, type._class.registered.name);
6270 strcat(string, type._class.string);
6277 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6278 if(funcType && funcType.kind == functionType)
6281 PrintType(funcType.returnType, string, false, fullName);
6282 strcat(string, "(*");
6283 if(printName || funcType.thisClass)
6285 strcat(string, " ");
6286 if(funcType.thisClass)
6288 strcat(string, funcType.thisClass.string);
6289 strcat(string, "::");
6292 strcat(string, type.name);
6294 strcat(string, ")(");
6295 for(param = funcType.params.first; param; param = param.next)
6297 PrintType(param, string, false, fullName);
6298 if(param.next) strcat(string, ", ");
6300 strcat(string, ")");
6304 _PrintType(type.type, string, false /*printName*/, printFunction, fullName);
6305 strcat(string, " *");
6309 case voidType: strcat(string, "void"); break;
6310 case intType: strcat(string, type.isSigned ? "int" : "uint"); break;
6311 case int64Type: strcat(string, type.isSigned ? "int64" : "uint64"); break;
6312 case intPtrType: strcat(string, type.isSigned ? "intptr" : "uintptr"); break;
6313 case charType: strcat(string, type.isSigned ? "char" : "byte"); break;
6314 case shortType: strcat(string, type.isSigned ? "short" : "uint16"); break;
6315 case floatType: strcat(string, "float"); break;
6316 case doubleType: strcat(string, "double"); break;
6320 strcat(string, "struct ");
6321 strcat(string, type.enumName);
6323 else if(type.typeName)
6325 strcat(string, type.typeName);
6330 strcat(string, "struct ");
6331 strcat(string,"(unnamed)");
6334 strcat(string, "struct {");
6335 for(member = type.members.first; member; member = member.next)
6337 PrintType(member, string, true, fullName);
6338 strcat(string,"; ");
6346 strcat(string, "union ");
6347 strcat(string, type.enumName);
6349 else if(type.typeName)
6351 strcat(string, type.typeName);
6355 strcat(string, "union ");
6356 strcat(string,"(unnamed)");
6362 strcat(string, "enum ");
6363 strcat(string, type.enumName);
6365 else if(type.typeName)
6367 strcat(string, type.typeName);
6370 strcat(string, "enum");
6377 strcat(string, "dllexport ");
6378 PrintType(type.returnType, string, false, fullName);
6379 strcat(string, " ");
6382 // DANGER: Testing This
6388 strcat(string, type.name);
6391 char * name = RSearchString(type.name, "::", strlen(type.name), true, false);
6392 if(name) name += 2; else name = type.name;
6393 strcat(string, name);
6407 strcat(string, "(");
6408 for(param = type.params.first; param; param = param.next)
6410 PrintType(param, string, true, fullName);
6411 if(param.next) strcat(string, ", ");
6413 strcat(string, ")");
6420 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6421 if(funcType && funcType.kind == functionType)
6424 PrintType(funcType.returnType, string, false, fullName);
6425 strcat(string, "(*");
6426 if(printName || funcType.thisClass)
6428 strcat(string, " ");
6429 if(funcType.thisClass)
6431 strcat(string, funcType.thisClass.string);
6432 strcat(string, "::");
6435 strcat(string, type.name);
6437 strcat(string, ")(");
6438 for(param = funcType.params.first; param; param = param.next)
6440 PrintType(param, string, false, fullName);
6441 if(param.next) strcat(string, ", ");
6443 strcat(string, ")");
6447 char baseType[1024], size[256];
6448 Type arrayType = type;
6452 while(arrayType.kind == TypeKind::arrayType)
6455 if(arrayType.enumClass)
6456 strcat(size, arrayType.enumClass.string);
6457 else if(arrayType.arraySizeExp)
6458 PrintExpression(arrayType.arraySizeExp, size);
6459 //sprintf(string, "%s[%s]", baseType, size);
6462 arrayType = arrayType.arrayType;
6464 _PrintType(arrayType, baseType, printName, printFunction, fullName);
6465 strcat(string, baseType);
6466 strcat(string, size);
6470 PrintType(type.arrayType, baseType, printName, fullName);
6472 strcpy(size, type.enumClass.string);
6473 else if(type.arraySizeExp)
6474 PrintExpression(type.arraySizeExp, size);
6475 //sprintf(string, "%s[%s]", baseType, size);
6476 strcat(string, baseType);
6477 strcat(string, "[");
6478 strcat(string, size);
6479 strcat(string, "]");
6486 strcat(string, "...");
6489 _PrintType(type.method.dataType, string, false, printFunction, fullName);
6492 strcat(string, "subclass(");
6493 strcat(string, type._class ? type._class.string : "int");
6494 strcat(string, ")");
6497 strcat(string, type.templateParameter.identifier.string);
6500 strcat(string, "thisclass");
6503 strcat(string, "__builtin_va_list");
6510 if(type.name && printName && type.kind != functionType && (type.kind != pointerType || type.type.kind != functionType))
6512 strcat(string, " ");
6513 strcat(string, type.name);
6519 // TODO: Add a max buffer size to avoid overflows. This function is used with static size char arrays.
6521 void PrintType(Type type, char * string, bool printName, bool fullName)
6524 for(funcType = type; funcType && (funcType.kind == pointerType || funcType.kind == arrayType); funcType = funcType.type);
6525 if(funcType && funcType.kind == functionType && type != funcType)
6527 char typeString[1024];
6530 PrintType(funcType.returnType, string, false, fullName);
6531 strcat(string, "(");
6532 _PrintType(type, string, printName, false, fullName);
6533 strcat(string, ")");
6536 strcat(string, type.name);
6542 strcat(string, "(");
6543 for(param = funcType.params.first; param; param = param.next)
6545 PrintType(param, string, true, fullName);
6546 if(param.next) strcat(string, ", ");
6548 strcat(string, ")");
6551 _PrintType(type, string, printName, true, fullName);
6552 if(type.bitFieldCount)
6555 sprintf(count, ":%d", type.bitFieldCount);
6556 strcat(string, count);
6560 static Type FindMember(Type type, char * string)
6563 for(memberType = type.members.first; memberType; memberType = memberType.next)
6565 if(!memberType.name)
6567 Type subType = FindMember(memberType, string);
6571 else if(!strcmp(memberType.name, string))
6577 Type FindMemberAndOffset(Type type, char * string, uint * offset)
6580 for(memberType = type.members.first; memberType; memberType = memberType.next)
6582 if(!memberType.name)
6584 Type subType = FindMember(memberType, string);
6587 *offset += memberType.offset;
6591 else if(!strcmp(memberType.name, string))
6593 *offset += memberType.offset;
6600 Expression ParseExpressionString(char * expression)
6602 fileInput = TempFile { };
6603 fileInput.Write(expression, 1, strlen(expression));
6604 fileInput.Seek(0, start);
6607 parsedExpression = null;
6609 expression_yyparse();
6612 return parsedExpression;
6615 static bool ResolveIdWithClass(Expression exp, Class _class, bool skipIDClassCheck)
6617 Identifier id = exp.identifier;
6618 Method method = null;
6619 Property prop = null;
6620 DataMember member = null;
6621 ClassProperty classProp = null;
6623 if(_class && _class.type == enumClass)
6625 NamedLink value = null;
6626 Class enumClass = eSystem_FindClass(privateModule, "enum");
6630 for(baseClass = _class; baseClass && baseClass.type == ClassType::enumClass; baseClass = baseClass.base)
6632 EnumClassData e = ACCESS_CLASSDATA(baseClass, enumClass);
6633 for(value = e.values.first; value; value = value.next)
6635 if(!strcmp(value.name, id.string))
6642 FreeExpContents(exp);
6644 exp.type = constantExp;
6645 exp.isConstant = true;
6646 if(!strcmp(baseClass.dataTypeString, "int"))
6647 sprintf(constant, "%d",value.data);
6649 sprintf(constant, "0x%X",value.data);
6650 exp.constant = CopyString(constant);
6651 //for(;_class.base && _class.base.type != systemClass; _class = _class.base);
6652 exp.expType = MkClassType(baseClass.fullName);
6660 if((method = eClass_FindMethod(_class, id.string, privateModule)))
6662 ProcessMethodType(method);
6669 // TOCHECK: Put it back to what it was...
6670 // methodClass = _class;
6671 methodClass = (skipIDClassCheck || (id && id._class)) ? _class : null;
6676 else if((prop = eClass_FindProperty(_class, id.string, privateModule)))
6679 ProcessPropertyType(prop);
6680 exp.expType = prop.dataType;
6681 if(prop.dataType) prop.dataType.refCount++;
6684 else if((member = eClass_FindDataMember(_class, id.string, privateModule, null, null)))
6686 if(!member.dataType)
6687 member.dataType = ProcessTypeString(member.dataTypeString, false);
6688 exp.expType = member.dataType;
6689 if(member.dataType) member.dataType.refCount++;
6692 else if((classProp = eClass_FindClassProperty(_class, id.string)))
6694 if(!classProp.dataType)
6695 classProp.dataType = ProcessTypeString(classProp.dataTypeString, false);
6697 if(classProp.constant)
6699 FreeExpContents(exp);
6701 exp.isConstant = true;
6702 if(classProp.dataType.kind == pointerType && classProp.dataType.type.kind == charType)
6704 //char constant[256];
6705 exp.type = stringExp;
6706 exp.constant = QMkString((char *)classProp.Get(_class));
6711 exp.type = constantExp;
6712 sprintf(constant, "%d", (int)classProp.Get(_class));
6713 exp.constant = CopyString(constant);
6721 exp.expType = classProp.dataType;
6722 if(classProp.dataType) classProp.dataType.refCount++;
6728 static GlobalData ScanGlobalData(NameSpace nameSpace, char * name)
6730 BinaryTree * tree = &nameSpace.functions;
6731 GlobalData data = (GlobalData)tree->FindString(name);
6735 for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
6737 data = ScanGlobalData(child, name);
6745 static GlobalData FindGlobalData(char * name)
6748 NameSpace * nameSpace;
6749 nameSpace = globalData;
6750 for(c = 0; name[c]; c++)
6752 if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
6754 NameSpace * newSpace;
6755 char * spaceName = new char[c - start + 1];
6756 strncpy(spaceName, name + start, c - start);
6757 spaceName[c-start] = '\0';
6758 newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
6762 nameSpace = newSpace;
6763 if(name[c] == ':') c++;
6769 return ScanGlobalData(nameSpace, name + start);
6774 static int definedExpStackPos;
6775 static void * definedExpStack[512];
6777 // This function makes checkedExp equivalent to newExp, ending up freeing newExp
6778 void ReplaceExpContents(Expression checkedExp, Expression newExp)
6780 Expression prev = checkedExp.prev, next = checkedExp.next;
6782 FreeExpContents(checkedExp);
6783 FreeType(checkedExp.expType);
6784 FreeType(checkedExp.destType);
6786 *checkedExp = *newExp;
6790 checkedExp.prev = prev;
6791 checkedExp.next = next;
6794 void ApplyAnyObjectLogic(Expression e)
6796 Type destType = /*(e.destType && e.destType.kind == ellipsisType) ? ellipsisDestType : */e.destType;
6797 if(destType && (/*destType.classObjectType == ClassObjectType::typedObject || */destType.classObjectType == anyObject))
6799 //if(e.destType && e.destType.kind == ellipsisType) usedEllipsis = true;
6800 //ellipsisDestType = destType;
6803 Type type = e.expType;
6804 Class _class = null;
6805 //Type destType = e.destType;
6807 if(type.kind == classType && type._class && type._class.registered)
6809 _class = type._class.registered;
6811 else if(type.kind == subClassType)
6813 _class = FindClass("ecere::com::Class").registered;
6817 char string[1024] = "";
6820 PrintType(type, string, false, true);
6821 classSym = FindClass(string);
6822 if(classSym) _class = classSym.registered;
6825 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...
6826 (!e.expType.classObjectType && (((type.kind != pointerType && type.kind != subClassType && (type.kind != classType || !type._class || !type._class.registered || type._class.registered.type == structClass))) ||
6827 destType.byReference)))
6829 if(!_class || strcmp(_class.fullName, "char *")) // TESTING THIS WITH NEW String class...
6831 Expression checkedExp = e, newExp;
6833 while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6835 if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6837 if(checkedExp.type == extensionCompoundExp)
6839 checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6842 checkedExp = checkedExp.list->last;
6844 else if(checkedExp.type == castExp)
6845 checkedExp = checkedExp.cast.exp;
6848 if(checkedExp && checkedExp.type == opExp && checkedExp.op.op == '*' && !checkedExp.op.exp1)
6850 newExp = checkedExp.op.exp2;
6851 checkedExp.op.exp2 = null;
6852 FreeExpContents(checkedExp);
6854 if(e.expType && e.expType.passAsTemplate)
6857 ComputeTypeSize(e.expType);
6858 sprintf(size, "%d", e.expType.size);
6859 newExp = MkExpBrackets(MkListOne(MkExpOp(MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)),
6860 MkDeclaratorPointer(MkPointer(null, null), null)), newExp), '+',
6861 MkExpCall(MkExpIdentifier(MkIdentifier("__ENDIAN_PAD")), MkListOne(MkExpConstant(size))))));
6864 ReplaceExpContents(checkedExp, newExp);
6865 e.byReference = true;
6867 else if(!e.byReference || (_class && _class.type == noHeadClass)) // TESTING THIS HERE...
6869 Expression checkedExp, newExp;
6872 // TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
6874 e.type == identifierExp ||
6875 (e.type == ExpressionType::memberExp && e.member.memberType == dataMember) ||
6876 (e.type == ExpressionType::pointerExp && e.member.memberType == dataMember) ||
6877 (e.type == opExp && !e.op.exp1 && e.op.op == '*') ||
6880 if(_class && _class.type != noHeadClass && _class.type != normalClass && _class.type != structClass && !hasAddress)
6882 Context context = PushContext();
6884 OldList * specs = MkList();
6885 char typeString[1024];
6886 Expression newExp { };
6888 typeString[0] = '\0';
6891 //if(e.destType) e.destType.refCount++;
6892 // if(exp.expType) exp.expType.refCount++;
6895 newExp.expType = null;
6897 PrintType(e.expType, typeString, false, true);
6898 decl = SpecDeclFromString(typeString, specs, null);
6899 newExp.destType = ProcessType(specs, decl);
6901 curContext = context;
6902 e.type = extensionCompoundExp;
6904 // We need a current compound for this
6908 OldList * stmts = MkList();
6909 sprintf(name, "__internalValue%03X", internalValueCounter++);
6910 if(!curCompound.compound.declarations)
6911 curCompound.compound.declarations = MkList();
6912 curCompound.compound.declarations->Insert(null, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(name)), null))));
6913 ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(MkIdentifier(name)), '=', newExp))));
6914 ListAdd(stmts, MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier(name)))));
6915 e.compound = MkCompoundStmt(null, stmts);
6918 printf("libec: compiler error, curCompound is null in ApplyAnyObjectLogic\n");
6921 e.compound = MkCompoundStmt(
6922 MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(
6923 MkDeclaratorIdentifier(MkIdentifier("__internalValue")), MkInitializerAssignment(newExp))))),
6925 MkListOne(MkExpressionStmt(MkListOne(MkExpIdentifier(MkIdentifier("__internalValue"))))));
6929 Type type = e.destType;
6931 CopyTypeInto(e.destType, type);
6932 e.destType.refCount = 1;
6933 e.destType.classObjectType = none;
6937 e.compound.compound.context = context;
6938 PopContext(context);
6939 curContext = context.parent;
6943 // TODO: INTEGRATE THIS WITH VERSION ABOVE WHICH WAS ADDED TO ENCOMPASS OTHER CASE (*pointer)
6945 while(((checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp) && checkedExp.list) || checkedExp.type == castExp)
6947 if(checkedExp.type == bracketsExp || checkedExp.type == extensionExpressionExp || checkedExp.type == extensionCompoundExp)
6949 if(checkedExp.type == extensionCompoundExp)
6951 checkedExp = ((Statement)checkedExp.compound.compound.statements->last).expressions->last;
6954 checkedExp = checkedExp.list->last;
6956 else if(checkedExp.type == castExp)
6957 checkedExp = checkedExp.cast.exp;
6960 Expression operand { };
6961 operand = *checkedExp;
6962 checkedExp.destType = null;
6963 checkedExp.expType = null;
6965 checkedExp.type = opExp;
6966 checkedExp.op.op = '&';
6967 checkedExp.op.exp1 = null;
6968 checkedExp.op.exp2 = operand;
6970 //newExp = MkExpOp(null, '&', checkedExp);
6972 //ReplaceExpContents(checkedExp, newExp);
6979 // If expression type is a simple class, make it an address
6980 // FixReference(e, true);
6983 if((!destType || destType.kind == ellipsisType || destType.kind == voidType) && e.expType && (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
6984 (e.expType.byReference || (e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
6985 (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass ) )))
6987 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class"))
6989 return; // LEAVE THIS CASE (typed_object & :: methods 's this) TO PASS 2 FOR NOW
6993 Expression thisExp { };
6996 thisExp.prev = null;
6997 thisExp.next = null;
7000 e.type = bracketsExp;
7001 e.list = MkListOne(MkExpOp(null, '*', MkExpBrackets(MkListOne(thisExp))));
7002 if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && thisExp.expType._class.registered.type == noHeadClass)
7003 ((Expression)e.list->first).byReference = true;
7005 /*if(thisExp.expType.kind == classType && thisExp.expType._class && thisExp.expType._class.registered && !strcmp(thisExp.expType._class.registered.name, "class"))
7007 e.expType = thisExp.expType;
7008 e.expType.refCount++;
7013 CopyTypeInto(e.expType, thisExp.expType);
7014 e.expType.byReference = false;
7015 e.expType.refCount = 1;
7017 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered &&
7018 (e.expType._class.registered.type == bitClass || e.expType._class.registered.type == enumClass || e.expType._class.registered.type == unitClass))
7020 e.expType.classObjectType = none;
7025 // TOFIX: Try this for a nice IDE crash!
7027 // The other way around
7030 if(destType && e.expType &&
7031 //e.expType.kind == classType && e.expType._class && e.expType._class.registered && !strcmp(e.expType._class.registered.name, "class") &&
7032 (e.expType.classObjectType == anyObject || e.expType.classObjectType == typedObject) &&
7033 !destType.classObjectType && /*(destType.kind != pointerType || !destType.type || destType.type.kind != voidType) &&*/ destType.kind != voidType)
7035 if(destType.kind == ellipsisType)
7037 Compiler_Error($"Unspecified type\n");
7039 else if(!(destType.truth && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass))
7041 bool byReference = e.expType.byReference;
7042 Expression thisExp { };
7044 OldList * specs = MkList();
7045 char typeString[1024]; // Watch buffer overruns
7047 ClassObjectType backupClassObjectType;
7049 if(e.expType.kind == classType && e.expType._class && e.expType._class.registered && strcmp(e.expType._class.registered.name, "class"))
7054 backupClassObjectType = type.classObjectType;
7056 type.classObjectType = none;
7058 typeString[0] = '\0';
7059 PrintType(type, typeString, false, true);
7060 decl = SpecDeclFromString(typeString, specs, null);
7062 type.classObjectType = backupClassObjectType;
7065 thisExp.prev = null;
7066 thisExp.next = null;
7069 if( ( type.kind == classType && type._class && type._class.registered && strcmp(type._class.registered.fullName, "ecere::com::Instance") &&
7070 (type._class.registered.type == systemClass || type._class.registered.type == bitClass ||
7071 type._class.registered.type == enumClass || type._class.registered.type == unitClass) ) ||
7072 (type.kind != pointerType && type.kind != arrayType && type.kind != classType) ||
7073 (!destType.byReference && byReference && (destType.kind != pointerType || type.kind != pointerType)))
7078 e.op.exp2 = MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), thisExp);
7083 e.cast.typeName = MkTypeName(specs, decl);
7084 e.cast.exp = thisExp;
7085 e.byReference = true;
7088 e.destType = destType;
7090 destType.refCount++;
7095 void ProcessExpressionType(Expression exp)
7097 bool unresolved = false;
7098 Location oldyylloc = yylloc;
7099 bool notByReference = false;
7101 char debugExpString[4096];
7102 debugExpString[0] = '\0';
7103 PrintExpression(exp, debugExpString);
7105 if(!exp || exp.expType)
7108 //eSystem_Logf("%s\n", expString);
7110 // Testing this here
7116 Identifier id = exp.identifier;
7119 // DOING THIS LATER NOW...
7120 if(id._class && id._class.name)
7122 id.classSym = id._class.symbol; // FindClass(id._class.name);
7123 /* TODO: Name Space Fix ups
7125 id.nameSpace = eSystem_FindNameSpace(privateModule, id._class.name);
7129 /* WHY WAS THIS COMMENTED OUT? if(!strcmp(id.string, "__thisModule"))
7131 exp.expType = ProcessTypeString("Module", true);
7134 else */if(strstr(id.string, "__ecereClass") == id.string)
7136 exp.expType = ProcessTypeString("ecere::com::Class", true);
7139 else if(id._class && (id.classSym || (id._class.name && !strcmp(id._class.name, "property"))))
7141 // Added this here as well
7142 ReplaceClassMembers(exp, thisClass);
7143 if(exp.type != identifierExp)
7145 ProcessExpressionType(exp);
7149 if(id.classSym && ResolveIdWithClass(exp, id.classSym.registered, false))
7154 Symbol symbol = FindSymbol(id.string, curContext, topContext /*exp.destType ? topContext : globalContext*/, false, id._class && id._class.name == null);
7155 // Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
7156 if(!symbol/* && exp.destType*/)
7158 if(exp.destType && CheckExpressionType(exp, exp.destType, false))
7164 ReplaceClassMembers(exp, thisClass ? thisClass : currentClass);
7165 if(exp.type != identifierExp)
7167 ProcessExpressionType(exp);
7171 // Static methods called from inside the _class
7172 else if(currentClass && !id._class)
7174 if(ResolveIdWithClass(exp, currentClass, true))
7177 symbol = FindSymbol(id.string, topContext.parent, globalContext, false, id._class && id._class.name == null);
7181 // If we manage to resolve this symbol
7184 Type type = symbol.type;
7185 Class _class = (type && type.kind == classType && type._class) ? type._class.registered : null;
7187 if(_class && !strcmp(id.string, "this") && !type.classObjectType)
7189 Context context = SetupTemplatesContext(_class);
7190 type = ReplaceThisClassType(_class);
7191 FinishTemplatesContext(context);
7192 if(type) type.refCount = 0; // We'll be incrementing it right below...
7195 FreeSpecifier(id._class);
7198 id.string = CopyString(symbol.string);
7204 if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
7205 // Add missing cases here... enum Classes...
7206 exp.isConstant = true;
7208 // TOCHECK: Why was !strcmp(id.string, "this") commented out?
7209 if(symbol.isParam || !strcmp(id.string, "this"))
7211 if(_class && _class.type == structClass)
7212 exp.byReference = true;
7214 //TESTING COMMENTING THIS OUT IN FAVOR OF ApplyAnyObjectLogic
7215 /*if(type && _class && (type.classObjectType == typedObject || type.classObjectType == anyObject) &&
7216 ((_class.type == unitClass || _class.type == enumClass || _class.type == bitClass) ||
7217 (type.byReference && (_class.type == normalClass || _class.type == noHeadClass))))
7219 Identifier id = exp.identifier;
7220 exp.type = bracketsExp;
7221 exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(id)));
7225 if(symbol.isIterator)
7227 if(symbol.isIterator == 3)
7229 exp.type = bracketsExp;
7230 exp.list = MkListOne(MkExpOp(null, '*', MkExpIdentifier(exp.identifier)));
7231 ((Expression)exp.list->first).op.exp2.expType = exp.expType;
7233 ProcessExpressionType(exp);
7235 else if(symbol.isIterator != 4)
7237 exp.type = memberExp;
7238 exp.member.exp = MkExpIdentifier(exp.identifier);
7239 exp.member.exp.expType = exp.expType;
7240 /*if(symbol.isIterator == 6)
7241 exp.member.member = MkIdentifier("key");
7243 exp.member.member = MkIdentifier("data");
7245 ProcessExpressionType(exp);
7252 DefinedExpression definedExp = null;
7253 if(thisNameSpace && !(id._class && !id._class.name))
7256 strcpy(name, thisNameSpace);
7258 strcat(name, id.string);
7259 definedExp = eSystem_FindDefine(privateModule, name);
7262 definedExp = eSystem_FindDefine(privateModule, id.string);
7266 for(c = 0; c<definedExpStackPos; c++)
7267 if(definedExpStack[c] == definedExp)
7269 if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
7271 Location backupYylloc = yylloc;
7272 definedExpStack[definedExpStackPos++] = definedExp;
7273 fileInput = TempFile { };
7274 fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
7275 fileInput.Seek(0, start);
7278 parsedExpression = null;
7280 expression_yyparse();
7283 yylloc = backupYylloc;
7285 if(parsedExpression)
7288 exp.type = bracketsExp;
7289 exp.list = MkListOne(parsedExpression);
7290 parsedExpression.loc = yylloc;
7291 ProcessExpressionType(exp);
7292 definedExpStackPos--;
7295 definedExpStackPos--;
7301 Compiler_Error($"Recursion in defined expression %s\n", id.string);
7307 GlobalData data = null;
7308 if(thisNameSpace && !(id._class && !id._class.name))
7311 strcpy(name, thisNameSpace);
7313 strcat(name, id.string);
7314 data = FindGlobalData(name);
7317 data = FindGlobalData(id.string);
7320 DeclareGlobalData(data);
7321 exp.expType = data.dataType;
7322 if(data.dataType) data.dataType.refCount++;
7325 id.string = CopyString(data.fullName);
7326 FreeSpecifier(id._class);
7333 GlobalFunction function = null;
7334 if(thisNameSpace && !(id._class && !id._class.name))
7337 strcpy(name, thisNameSpace);
7339 strcat(name, id.string);
7340 function = eSystem_FindFunction(privateModule, name);
7343 function = eSystem_FindFunction(privateModule, id.string);
7348 id.string = CopyString(function.name);
7351 if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
7352 strcpy(name, "__ecereFunction_");
7353 FullClassNameCat(name, id.string, false); // Why is this using FullClassNameCat ?
7354 if(DeclareFunction(function, name))
7357 id.string = CopyString(name);
7359 exp.expType = function.dataType;
7360 if(function.dataType) function.dataType.refCount++;
7362 FreeSpecifier(id._class);
7379 if(!exp.instance._class)
7381 if(exp.destType && exp.destType.kind == classType && exp.destType._class)
7383 exp.instance._class = MkSpecifierName(exp.destType._class.string);
7393 //classSym = FindClass(exp.instance._class.fullName);
7394 //_class = classSym ? classSym.registered : null;
7396 ProcessInstantiationType(exp.instance);
7397 exp.isConstant = exp.instance.isConstant;
7400 if(_class.type == unitClass && _class.base.type != systemClass)
7403 Type destType = exp.destType;
7405 exp.destType = MkClassType(_class.base.fullName);
7406 exp.expType = MkClassType(_class.fullName);
7407 CheckExpressionType(exp, exp.destType, true);
7409 exp.destType = destType;
7411 exp.expType = MkClassType(_class.fullName);
7414 if(exp.instance._class)
7416 exp.expType = MkClassType(exp.instance._class.name);
7417 /*if(exp.expType._class && exp.expType._class.registered &&
7418 (exp.expType._class.registered.type == normalClass || exp.expType._class.registered.type == noHeadClass))
7419 exp.expType.byReference = true;*/
7434 if(exp.constant[0] == '\'')
7436 if((int)((byte *)exp.constant)[1] > 127)
7439 unichar ch = UTF8GetChar(exp.constant + 1, &nb);
7440 if(nb < 2) ch = exp.constant[1];
7441 delete exp.constant;
7442 exp.constant = PrintUInt(ch);
7443 // type.kind = (ch > 0xFFFF) ? intType : shortType;
7444 type.kind = classType; //(ch > 0xFFFF) ? intType : shortType;
7445 type._class = FindClass("unichar");
7447 type.isSigned = false;
7451 type.kind = charType;
7452 type.isSigned = true;
7455 else if(strchr(exp.constant, '.'))
7457 char ch = exp.constant[strlen(exp.constant)-1];
7459 type.kind = floatType;
7461 type.kind = doubleType;
7462 type.isSigned = true;
7466 if(exp.constant[0] == '0' && exp.constant[1])
7467 type.isSigned = false;
7468 else if(strchr(exp.constant, 'L') || strchr(exp.constant, 'l'))
7469 type.isSigned = false;
7470 else if(strtoll(exp.constant, null, 0) > MAXINT)
7471 type.isSigned = false;
7473 type.isSigned = true;
7474 type.kind = intType;
7476 exp.isConstant = true;
7482 exp.isConstant = true; // Why wasn't this constant?
7498 ProcessExpressionType(exp._new.size);
7503 type = ProcessType(exp._new.typeName.qualifiers, exp._new.typeName.declarator);
7505 DeclareType(exp.expType.type, false, false);
7509 ProcessExpressionType(exp._renew.size);
7510 ProcessExpressionType(exp._renew.exp);
7515 type = ProcessType(exp._renew.typeName.qualifiers, exp._renew.typeName.declarator);
7517 DeclareType(exp.expType.type, false, false);
7521 bool assign = false, boolResult = false, boolOps = false;
7522 Type type1 = null, type2 = null;
7523 bool useDestType = false, useSideType = false;
7524 Location oldyylloc = yylloc;
7525 bool useSideUnit = false;
7527 // Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
7536 // Assignment Operators
7550 // boolean Operators
7552 // Expect boolean operators
7554 //boolResult = true;
7558 // Expect boolean operands
7569 // Gives boolean result
7577 // Just added these... testing
7582 // DANGER: Verify units
7587 if(exp.op.op != '*' || exp.op.exp1)
7594 /*// Implement speed etc.
7600 if(exp.op.op == '&')
7602 // Added this here earlier for Iterator address as key
7603 if(!exp.op.exp1 && exp.op.exp2 && exp.op.exp2.type == identifierExp && exp.op.exp2.identifier)
7605 Identifier id = exp.op.exp2.identifier;
7606 Symbol symbol = FindSymbol(id.string, curContext, topContext, false, id._class && id._class.name == null);
7607 if(symbol && symbol.isIterator == 2)
7609 exp.type = memberExp;
7610 exp.member.exp = exp.op.exp2;
7611 exp.member.member = MkIdentifier("key");
7613 exp.op.exp2.expType = symbol.type;
7614 symbol.type.refCount++;
7615 ProcessExpressionType(exp);
7619 // exp.op.exp2.usage.usageRef = true;
7623 //dummy.kind = TypeDummy;
7627 if(exp.destType && exp.destType.kind == classType &&
7628 exp.destType._class && exp.destType._class.registered && useDestType &&
7630 ((exp.destType._class.registered.type == unitClass && useSideUnit) ||
7631 exp.destType._class.registered.type == enumClass ||
7632 exp.destType._class.registered.type == bitClass
7635 //(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
7637 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7638 exp.op.exp1.destType = exp.destType;
7640 exp.destType.refCount++;
7644 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7645 exp.op.exp1.destType = dummy;
7649 // TESTING THIS HERE...
7650 if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
7651 ProcessExpressionType(exp.op.exp1);
7652 if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
7654 if(exp.op.exp1.destType == dummy)
7657 exp.op.exp1.destType = null;
7659 type1 = exp.op.exp1.expType;
7664 char expString[10240];
7665 expString[0] = '\0';
7666 if(exp.op.exp2.type == instanceExp && !exp.op.exp2.instance._class)
7670 exp.op.exp2.destType = exp.op.exp1.expType;
7671 if(exp.op.exp1.expType)
7672 exp.op.exp1.expType.refCount++;
7676 exp.op.exp2.destType = exp.destType;
7678 exp.destType.refCount++;
7681 if(type1) type1.refCount++;
7682 exp.expType = type1;
7687 PrintExpression(exp.op.exp2, expString);
7689 if(type1 && type1.kind == pointerType)
7691 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 ||
7692 exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN)
7693 Compiler_Error($"operator %s illegal on pointer\n", exp.op.op);
7694 else if(exp.op.op == '=')
7696 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7697 exp.op.exp2.destType = type1;
7704 // Don't convert to the type for those... (e.g.: Degrees a; a /= 2;)
7705 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/* ||
7706 exp.op.op == AND_ASSIGN || exp.op.op == OR_ASSIGN*/);
7709 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7710 exp.op.exp2.destType = type1;
7715 if(type1) type1.refCount++;
7716 exp.expType = type1;
7718 else if(exp.destType && exp.destType.kind == classType &&
7719 exp.destType._class && exp.destType._class.registered &&
7721 ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) ||
7722 (exp.destType._class.registered.type == enumClass && useDestType))
7725 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7726 exp.op.exp2.destType = exp.destType;
7728 exp.destType.refCount++;
7732 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7733 exp.op.exp2.destType = dummy;
7737 // TESTING THIS HERE... (DANGEROUS)
7738 if(type1 && boolResult && useSideType && type1.kind == classType && type1._class && type1._class.registered &&
7739 (type1._class.registered.type == bitClass || type1._class.registered.type == enumClass))
7741 FreeType(exp.op.exp2.destType);
7742 exp.op.exp2.destType = type1;
7745 if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
7746 ProcessExpressionType(exp.op.exp2);
7747 if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
7749 if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
7751 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)
7753 if(exp.op.op != '=' && type1.type.kind == voidType)
7754 Compiler_Error($"void *: unknown size\n");
7756 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||
7757 (type1.type.kind == voidType && exp.op.exp2.expType.kind == classType && exp.op.exp2.expType._class.registered &&
7758 (exp.op.exp2.expType._class.registered.type == normalClass ||
7759 exp.op.exp2.expType._class.registered.type == structClass ||
7760 exp.op.exp2.expType._class.registered.type == noHeadClass)))
7762 if(exp.op.op == ADD_ASSIGN)
7763 Compiler_Error($"cannot add two pointers\n");
7765 else if((exp.op.exp2.expType.kind == classType && type1.kind == pointerType && type1.type.kind == classType &&
7766 type1.type._class == exp.op.exp2.expType._class && exp.op.exp2.expType._class.registered && exp.op.exp2.expType._class.registered.type == structClass))
7768 if(exp.op.op == ADD_ASSIGN)
7769 Compiler_Error($"cannot add two pointers\n");
7773 char type1String[1024];
7774 char type2String[1024];
7775 type1String[0] = '\0';
7776 type2String[0] = '\0';
7778 PrintType(exp.op.exp2.expType, type1String, false, true);
7779 PrintType(type1, type2String, false, true);
7780 ChangeCh(expString, '\n', ' ');
7781 Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1String, type2String);
7785 if(exp.op.exp2.destType == dummy)
7788 exp.op.exp2.destType = null;
7791 type2 = exp.op.exp2.expType;
7794 dummy.kind = voidType;
7796 if(exp.op.op == SIZEOF)
7803 exp.isConstant = true;
7805 // Get type of dereferenced pointer
7806 else if(exp.op.op == '*' && !exp.op.exp1)
7808 exp.expType = Dereference(type2);
7809 if(type2 && type2.kind == classType)
7810 notByReference = true;
7812 else if(exp.op.op == '&' && !exp.op.exp1)
7813 exp.expType = Reference(type2);
7820 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7821 exp.op.exp1.destType = MkClassType("bool");
7822 exp.op.exp1.destType.truth = true;
7823 if(!exp.op.exp1.expType)
7824 ProcessExpressionType(exp.op.exp1);
7826 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
7827 FreeType(exp.op.exp1.expType);
7828 exp.op.exp1.expType = MkClassType("bool");
7829 exp.op.exp1.expType.truth = true;
7833 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7834 exp.op.exp2.destType = MkClassType("bool");
7835 exp.op.exp2.destType.truth = true;
7836 if(!exp.op.exp2.expType)
7837 ProcessExpressionType(exp.op.exp2);
7839 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
7840 FreeType(exp.op.exp2.expType);
7841 exp.op.exp2.expType = MkClassType("bool");
7842 exp.op.exp2.expType.truth = true;
7845 else if(exp.op.exp1 && exp.op.exp2 &&
7848 ((!type1 || type1.kind != classType || type1._class.registered.type != unitClass) &&
7849 (!type2 || type2.kind != classType || type2._class.registered.type != unitClass)))*/) ||
7850 ((!type1 || type1.kind != classType || !strcmp(type1._class.string, "String")) &&
7851 (!type2 || type2.kind != classType || !strcmp(type2._class.string, "String")))))
7853 if(type1 && type2 &&
7854 // If either both are class or both are not class
7855 ((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
7857 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
7858 exp.op.exp2.destType = type1;
7860 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
7861 exp.op.exp1.destType = type2;
7863 // Warning here for adding Radians + Degrees with no destination type
7864 if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) &&
7865 type1._class.registered && type1._class.registered.type == unitClass &&
7866 type2._class.registered && type2._class.registered.type == unitClass &&
7867 type1._class.registered != type2._class.registered)
7868 Compiler_Warning($"operating on %s and %s with an untyped result, assuming %s\n",
7869 type1._class.string, type2._class.string, type1._class.string);
7871 if(type1.kind == pointerType && type1.type.kind == templateType && type2.kind != pointerType)
7873 Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7876 Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7878 exp.op.exp1 = MkExpBrackets(MkListOne(MkExpCast(
7879 MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)),
7882 ProcessExpressionType(exp.op.exp1);
7884 if(type2.kind != pointerType)
7886 ProcessExpressionType(classExp);
7888 exp.op.exp2 = MkExpBrackets(MkListOne(MkExpOp(exp.op.exp2, '*',
7889 // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7890 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7892 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("5")),
7895 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpConstant("0"))))),
7896 MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7897 MkPointer(null, null), null)))),
7898 MkExpMember(classExp, MkIdentifier("typeSize"))))))));
7900 if(!exp.op.exp2.expType)
7901 type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
7903 ProcessExpressionType(exp.op.exp2);
7908 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)))
7910 if(type1.kind != classType && type1.type.kind == voidType)
7911 Compiler_Error($"void *: unknown size\n");
7912 exp.expType = type1;
7913 if(type1) type1.refCount++;
7915 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)))
7917 if(type2.kind != classType && type2.type.kind == voidType)
7918 Compiler_Error($"void *: unknown size\n");
7919 exp.expType = type2;
7920 if(type2) type2.refCount++;
7922 else if((type1.kind == pointerType && type2.kind != pointerType && type2.kind != arrayType && type2.kind != functionType && type2.kind != methodType && type2.kind != classType && type2.kind != subClassType) ||
7923 (type2.kind == pointerType && type1.kind != pointerType && type1.kind != arrayType && type1.kind != functionType && type1.kind != methodType && type1.kind != classType && type1.kind != subClassType))
7925 Compiler_Warning($"different levels of indirection\n");
7929 bool success = false;
7930 if(type1.kind == pointerType && type2.kind == pointerType)
7932 if(exp.op.op == '+')
7933 Compiler_Error($"cannot add two pointers\n");
7934 else if(exp.op.op == '-')
7936 // Pointer Subtraction gives integer
7937 if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
7946 if(type1.type.kind == templateType)
7948 Expression argExp = GetTemplateArgExp(type1.type.templateParameter, thisClass, true);
7951 Expression classExp = MkExpMember(argExp, MkIdentifier("dataTypeClass"));
7953 ProcessExpressionType(classExp);
7955 exp.type = bracketsExp;
7956 exp.list = MkListOne(MkExpOp(
7957 MkExpBrackets(MkListOne(MkExpOp(
7958 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp1)))
7960 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), MkExpBrackets(MkListOne(exp.op.exp2)))))), '/',
7962 //MkExpMember(classExp, MkIdentifier("typeSize"))
7964 // ((_class.type == noHeadClass || _class.type == normalClass) ? sizeof(void *) : type.size)
7965 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(MkExpOp(
7967 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("noHeadClass"))),
7970 MkExpOp(MkExpMember(CopyExpression(classExp), MkIdentifier("type")), EQ_OP, MkExpIdentifier(MkIdentifier("normalClass")))))),
7971 MkListOne(MkExpTypeSize(MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(
7972 MkPointer(null, null), null)))),
7973 MkExpMember(classExp, MkIdentifier("typeSize")))))
7978 ProcessExpressionType(((Expression)exp.list->first).op.exp2);
7987 if(!success && exp.op.exp1.type == constantExp)
7989 // If first expression is constant, try to match that first
7990 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
7992 if(exp.expType) FreeType(exp.expType);
7993 exp.expType = exp.op.exp1.destType;
7994 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
7997 else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
7999 if(exp.expType) FreeType(exp.expType);
8000 exp.expType = exp.op.exp2.destType;
8001 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8007 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8009 if(exp.expType) FreeType(exp.expType);
8010 exp.expType = exp.op.exp2.destType;
8011 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8014 else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8016 if(exp.expType) FreeType(exp.expType);
8017 exp.expType = exp.op.exp1.destType;
8018 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8024 char expString1[10240];
8025 char expString2[10240];
8028 expString1[0] = '\0';
8029 expString2[0] = '\0';
8034 PrintExpression(exp.op.exp1, expString1);
8035 ChangeCh(expString1, '\n', ' ');
8036 PrintExpression(exp.op.exp2, expString2);
8037 ChangeCh(expString2, '\n', ' ');
8038 PrintType(exp.op.exp1.expType, type1, false, true);
8039 PrintType(exp.op.exp2.expType, type2, false, true);
8042 Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1, expString2, type2);
8046 // ADDED THESE TWO FROM OUTSIDE useSideType CHECK
8047 else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type2 && type1 && type2.kind == classType && type1.kind != classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8049 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8050 // Convert e.g. / 4 into / 4.0
8051 exp.op.exp1.destType = type2._class.registered.dataType;
8052 if(type2._class.registered.dataType)
8053 type2._class.registered.dataType.refCount++;
8054 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8055 exp.expType = type2;
8056 if(type2) type2.refCount++;
8058 else if(!boolResult && (!useSideUnit /*|| exp.destType*/) && type1 && type2 && type1.kind == classType && type2.kind != classType && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8060 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8061 // Convert e.g. / 4 into / 4.0
8062 exp.op.exp2.destType = type1._class.registered.dataType;
8063 if(type1._class.registered.dataType)
8064 type1._class.registered.dataType.refCount++;
8065 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8066 exp.expType = type1;
8067 if(type1) type1.refCount++;
8073 if(!boolResult && useSideUnit && type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8075 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8077 if(!type1._class.registered.dataType)
8078 type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
8079 exp.op.exp2.destType = type1._class.registered.dataType;
8080 exp.op.exp2.destType.refCount++;
8082 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8083 type2 = exp.op.exp2.destType;
8085 exp.expType = type2;
8089 if(!boolResult && useSideUnit && type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8091 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8093 if(!type2._class.registered.dataType)
8094 type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
8095 exp.op.exp1.destType = type2._class.registered.dataType;
8096 exp.op.exp1.destType.refCount++;
8098 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8099 type1 = exp.op.exp1.destType;
8100 exp.expType = type1;
8104 // TESTING THIS NEW CODE
8105 if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
8107 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
8109 if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
8111 if(exp.expType) FreeType(exp.expType);
8112 exp.expType = exp.op.exp1.expType;
8113 if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
8118 else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
8120 if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
8122 if(exp.expType) FreeType(exp.expType);
8123 exp.expType = exp.op.exp2.expType;
8124 if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8132 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8133 exp.op.exp2.destType = type1;
8137 // Maybe this was meant to be an enum...
8138 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8140 Type oldType = exp.op.exp2.expType;
8141 exp.op.exp2.expType = null;
8142 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8145 exp.op.exp2.expType = oldType;
8150 // TESTING THIS HERE... LATEST ADDITION
8151 if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8153 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8154 exp.op.exp2.destType = type2._class.registered.dataType;
8155 if(type2._class.registered.dataType)
8156 type2._class.registered.dataType.refCount++;
8157 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8159 //exp.expType = type2._class.registered.dataType; //type2;
8160 //if(type2) type2.refCount++;
8163 // TESTING THIS HERE... LATEST ADDITION
8164 if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8166 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8167 exp.op.exp1.destType = type1._class.registered.dataType;
8168 if(type1._class.registered.dataType)
8169 type1._class.registered.dataType.refCount++;
8170 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8171 exp.expType = type1._class.registered.dataType; //type1;
8172 if(type1) type1.refCount++;
8176 if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
8178 if(exp.expType) FreeType(exp.expType);
8179 exp.expType = exp.op.exp2.destType;
8180 if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
8182 else if(type1 && type2)
8184 char expString1[10240];
8185 char expString2[10240];
8186 char type1String[1024];
8187 char type2String[1024];
8188 expString1[0] = '\0';
8189 expString2[0] = '\0';
8190 type1String[0] = '\0';
8191 type2String[0] = '\0';
8194 PrintExpression(exp.op.exp1, expString1);
8195 ChangeCh(expString1, '\n', ' ');
8196 PrintExpression(exp.op.exp2, expString2);
8197 ChangeCh(expString2, '\n', ' ');
8198 PrintType(exp.op.exp1.expType, type1String, false, true);
8199 PrintType(exp.op.exp2.expType, type2String, false, true);
8202 Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
8204 if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
8206 exp.expType = exp.op.exp1.expType;
8207 if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
8209 else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8211 exp.expType = exp.op.exp2.expType;
8212 if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
8219 // Maybe this was meant to be an enum...
8220 if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
8222 Type oldType = exp.op.exp1.expType;
8223 exp.op.exp1.expType = null;
8224 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8227 exp.op.exp1.expType = oldType;
8230 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8231 exp.op.exp1.destType = type2;
8234 // TESTING THIS HERE... LATEST ADDITION
8235 if(type1 && type1.kind == classType && type1._class.registered && type1._class.registered.type == unitClass && type2 && type2.kind != classType)
8237 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8238 exp.op.exp1.destType = type1._class.registered.dataType;
8239 if(type1._class.registered.dataType)
8240 type1._class.registered.dataType.refCount++;
8243 // TESTING THIS HERE... LATEST ADDITION
8244 if(type2 && type2.kind == classType && type2._class.registered && type2._class.registered.type == unitClass && type1 && type1.kind != classType)
8246 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8247 exp.op.exp2.destType = type2._class.registered.dataType;
8248 if(type2._class.registered.dataType)
8249 type2._class.registered.dataType.refCount++;
8253 if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
8255 if(exp.expType) FreeType(exp.expType);
8256 exp.expType = exp.op.exp1.destType;
8257 if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
8261 else if(type2 && (!type1 || (type2.kind == classType && type1.kind != classType)))
8263 if(type1 && type2._class && type2._class.registered && type2._class.registered.type == unitClass)
8265 if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
8266 // Convert e.g. / 4 into / 4.0
8267 exp.op.exp1.destType = type2._class.registered.dataType;
8268 if(type2._class.registered.dataType)
8269 type2._class.registered.dataType.refCount++;
8270 CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
8272 if(exp.op.op == '!')
8274 exp.expType = MkClassType("bool");
8275 exp.expType.truth = true;
8279 exp.expType = type2;
8280 if(type2) type2.refCount++;
8283 else if(type1 && (!type2 || (type1.kind == classType && type2.kind != classType)))
8285 if(type2 && type1._class && type1._class.registered && type1._class.registered.type == unitClass)
8287 if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
8288 // Convert e.g. / 4 into / 4.0
8289 exp.op.exp2.destType = type1._class.registered.dataType;
8290 if(type1._class.registered.dataType)
8291 type1._class.registered.dataType.refCount++;
8292 CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
8294 exp.expType = type1;
8295 if(type1) type1.refCount++;
8300 if(exp.op.exp1 && !exp.op.exp1.expType)
8302 char expString[10000];
8303 expString[0] = '\0';
8306 PrintExpression(exp.op.exp1, expString);
8307 ChangeCh(expString, '\n', ' ');
8310 Compiler_Error($"couldn't determine type of %s\n", expString);
8312 if(exp.op.exp2 && !exp.op.exp2.expType)
8314 char expString[10240];
8315 expString[0] = '\0';
8318 PrintExpression(exp.op.exp2, expString);
8319 ChangeCh(expString, '\n', ' ');
8322 Compiler_Error($"couldn't determine type of %s\n", expString);
8327 FreeType(exp.expType);
8328 exp.expType = MkClassType("bool");
8329 exp.expType.truth = true;
8332 if(exp.op.op != SIZEOF)
8333 exp.isConstant = (!exp.op.exp1 || exp.op.exp1.isConstant) &&
8334 (!exp.op.exp2 || exp.op.exp2.isConstant);
8336 if(exp.op.op == SIZEOF && exp.op.exp2.expType)
8338 DeclareType(exp.op.exp2.expType, false, false);
8347 case extensionExpressionExp:
8350 exp.isConstant = true;
8351 for(e = exp.list->first; e; e = e.next)
8356 FreeType(e.destType);
8357 e.destType = exp.destType;
8358 if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
8360 ProcessExpressionType(e);
8362 exp.destType.count--;
8363 if(!exp.expType && !e.next)
8365 exp.expType = e.expType;
8366 if(e.expType) e.expType.refCount++;
8369 exp.isConstant = false;
8372 // In case a cast became a member...
8373 e = exp.list->first;
8374 if(!e.next && e.type == memberExp)
8376 // Preserve prev, next
8377 Expression next = exp.next, prev = exp.prev;
8380 FreeType(exp.expType);
8381 FreeType(exp.destType);
8391 ProcessExpressionType(exp);
8398 exp.isConstant = true;
8400 ProcessExpressionType(exp.index.exp);
8401 if(!exp.index.exp.isConstant)
8402 exp.isConstant = false;
8404 if(exp.index.exp.expType)
8406 Type source = exp.index.exp.expType;
8407 if(source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
8408 eClass_IsDerived(source._class.registered, containerClass) &&
8409 source._class.registered.templateArgs)
8411 Class _class = source._class.registered;
8412 exp.expType = ProcessTypeString(_class.templateArgs[2].dataTypeString, false);
8414 if(exp.index.index && exp.index.index->last)
8416 ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
8421 for(e = exp.index.index->first; e; e = e.next)
8423 if(!e.next && exp.index.exp.expType && exp.index.exp.expType.kind == arrayType && exp.index.exp.expType.enumClass)
8425 if(e.destType) FreeType(e.destType);
8426 e.destType = MkClassType(exp.index.exp.expType.enumClass.string);
8428 ProcessExpressionType(e);
8431 // Check if this type is int
8434 exp.isConstant = false;
8438 exp.expType = Dereference(exp.index.exp.expType);
8440 DeclareType(exp.expType, false, false);
8447 Type methodType = null;
8453 PrintExpression(exp.call.exp, name);
8454 if(exp.call.exp.expType && !exp.call.exp.expType.returnType)
8456 //exp.call.exp.expType = null;
8457 PrintExpression(exp.call.exp, name);
8460 if(exp.call.exp.type == identifierExp)
8462 Expression idExp = exp.call.exp;
8463 Identifier id = idExp.identifier;
8464 if(!strcmp(id.string, "__builtin_frame_address"))
8466 exp.expType = ProcessTypeString("void *", true);
8467 if(exp.call.arguments && exp.call.arguments->first)
8468 ProcessExpressionType(exp.call.arguments->first);
8471 else if(!strcmp(id.string, "__ENDIAN_PAD"))
8473 exp.expType = ProcessTypeString("int", true);
8474 if(exp.call.arguments && exp.call.arguments->first)
8475 ProcessExpressionType(exp.call.arguments->first);
8478 else if(!strcmp(id.string, "Max") ||
8479 !strcmp(id.string, "Min") ||
8480 !strcmp(id.string, "Sgn") ||
8481 !strcmp(id.string, "Abs"))
8483 Expression a = null;
8484 Expression b = null;
8485 Expression tempExp1 = null, tempExp2 = null;
8486 if((!strcmp(id.string, "Max") ||
8487 !strcmp(id.string, "Min")) && exp.call.arguments->count == 2)
8489 a = exp.call.arguments->first;
8490 b = exp.call.arguments->last;
8494 else if(exp.call.arguments->count == 1)
8496 a = exp.call.arguments->first;
8502 exp.call.arguments->Clear();
8503 idExp.identifier = null;
8505 FreeExpContents(exp);
8507 ProcessExpressionType(a);
8509 ProcessExpressionType(b);
8511 exp.type = bracketsExp;
8512 exp.list = MkList();
8514 if(a.expType && (!b || b.expType))
8516 if((!a.isConstant && a.type != identifierExp) || (b && !b.isConstant && b.type != identifierExp))
8518 // Use the simpleStruct name/ids for now...
8521 OldList * specs = MkList();
8522 OldList * decls = MkList();
8524 char temp1[1024], temp2[1024];
8526 GetTypeSpecs(a.expType, specs);
8528 if(a && !a.isConstant && a.type != identifierExp)
8530 sprintf(temp1, "__simpleStruct%d", curContext.simpleID++);
8531 ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp1)), null));
8532 tempExp1 = QMkExpId(temp1);
8533 tempExp1.expType = a.expType;
8535 a.expType.refCount++;
8536 ListAdd(exp.list, MkExpOp(CopyExpression(tempExp1), '=', a));
8538 if(b && !b.isConstant && b.type != identifierExp)
8540 sprintf(temp2, "__simpleStruct%d", curContext.simpleID++);
8541 ListAdd(decls, MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(temp2)), null));
8542 tempExp2 = QMkExpId(temp2);
8543 tempExp2.expType = b.expType;
8545 b.expType.refCount++;
8546 ListAdd(exp.list, MkExpOp(CopyExpression(tempExp2), '=', b));
8549 decl = MkDeclaration(specs, decls);
8550 if(!curCompound.compound.declarations)
8551 curCompound.compound.declarations = MkList();
8552 curCompound.compound.declarations->Insert(null, decl);
8557 if(!strcmp(id.string, "Max") || !strcmp(id.string, "Min"))
8559 int op = (!strcmp(id.string, "Max")) ? '>' : '<';
8561 MkExpCondition(MkExpBrackets(MkListOne(
8562 MkExpOp(CopyExpression(tempExp1), op, CopyExpression(tempExp2)))),
8563 MkListOne(CopyExpression(tempExp1)), CopyExpression(tempExp2)));
8564 exp.expType = a.expType;
8566 a.expType.refCount++;
8568 else if(!strcmp(id.string, "Abs"))
8571 MkExpCondition(MkExpBrackets(MkListOne(
8572 MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8573 MkListOne(MkExpOp(null, '-', CopyExpression(tempExp1))), CopyExpression(tempExp1)));
8574 exp.expType = a.expType;
8576 a.expType.refCount++;
8578 else if(!strcmp(id.string, "Sgn"))
8580 // ((!(a))?(0):(((a)<0)?(-1):(1)))
8582 MkExpCondition(MkExpBrackets(MkListOne(
8583 MkExpOp(null, '!', CopyExpression(tempExp1)))), MkListOne(MkExpConstant("0")),
8584 MkExpBrackets(MkListOne(MkExpCondition(MkExpBrackets(MkListOne(
8585 MkExpOp(CopyExpression(tempExp1), '<', MkExpConstant("0")))),
8586 MkListOne(MkExpConstant("-1")), MkExpConstant("1"))))));
8587 exp.expType = ProcessTypeString("int", false);
8590 FreeExpression(tempExp1);
8591 if(tempExp2) FreeExpression(tempExp2);
8605 if(!exp.call.exp.destType)
8607 exp.call.exp.destType = dummy;
8610 ProcessExpressionType(exp.call.exp);
8611 if(exp.call.exp.destType == dummy)
8614 exp.call.exp.destType = null;
8619 // Check argument types against parameter types
8620 functionType = exp.call.exp.expType;
8622 if(functionType && functionType.kind == TypeKind::methodType)
8624 methodType = functionType;
8625 functionType = methodType.method.dataType;
8627 //if(functionType.returnType && functionType.returnType.kind == thisClassType)
8628 // TOCHECK: Instead of doing this here could this be done per param?
8629 if(exp.call.exp.expType.usedClass)
8631 char typeString[1024];
8632 typeString[0] = '\0';
8633 PrintType(functionType, typeString, true, true);
8634 if(strstr(typeString, "thisclass"))
8636 OldList * specs = MkList();
8639 Context context = SetupTemplatesContext(exp.call.exp.expType.usedClass);
8641 decl = SpecDeclFromString(typeString, specs, null);
8643 // SET THIS TO FALSE WHEN PROCESSING THISCLASS OUTSIDE THE CLASS
8644 if(thisClass != (exp.call.exp.expType.usedClass.templateClass ? exp.call.exp.expType.usedClass.templateClass :
8645 exp.call.exp.expType.usedClass))
8646 thisClassParams = false;
8648 ReplaceThisClassSpecifiers(specs, exp.call.exp.expType.usedClass);
8650 Class backupThisClass = thisClass;
8651 thisClass = exp.call.exp.expType.usedClass;
8652 ProcessDeclarator(decl);
8653 thisClass = backupThisClass;
8656 thisClassParams = true;
8658 functionType = ProcessType(specs, decl);
8659 functionType.refCount = 0;
8660 FinishTemplatesContext(context);
8663 FreeList(specs, FreeSpecifier);
8664 FreeDeclarator(decl);
8668 if(functionType && functionType.kind == pointerType && functionType.type && functionType.type.kind == TypeKind::functionType)
8670 Type type = functionType.type;
8671 if(!functionType.refCount)
8673 functionType.type = null;
8674 FreeType(functionType);
8676 //methodType = functionType;
8677 functionType = type;
8679 if(functionType && functionType.kind != TypeKind::functionType)
8681 Compiler_Error($"called object %s is not a function\n", name);
8683 else if(functionType)
8685 bool emptyParams = false, noParams = false;
8686 Expression e = exp.call.arguments ? exp.call.arguments->first : null;
8687 Type type = functionType.params.first;
8688 Expression memberExp = (exp.call.exp.type == ExpressionType::memberExp) ? exp.call.exp : null;
8690 Location oldyylloc = yylloc;
8692 if(!type) emptyParams = true;
8695 if(functionType.extraParam && e)
8697 e.destType = MkClassType(functionType.thisClass.string);
8701 // WHY WAS THIS COMMENTED OUT ? Broke DisplaySystem::FontExtent(this ? displaySystem : null, font, text, len, width, height);
8702 if(!functionType.staticMethod)
8704 if(memberExp && memberExp.member.exp && memberExp.member.exp.expType && memberExp.member.exp.expType.kind == subClassType &&
8705 memberExp.member.exp.expType._class)
8707 type = MkClassType(memberExp.member.exp.expType._class.string);
8712 type = functionType.params.first;
8717 else if(!memberExp && (functionType.thisClass || (methodType && methodType.methodClass)))
8719 type = MkClassType(functionType.thisClass ? functionType.thisClass.string : (methodType ? methodType.methodClass.fullName : null));
8724 type = functionType.params.first;
8732 if(type && type.kind == voidType)
8735 if(!type.refCount) FreeType(type);
8739 for( ; e; e = e.next)
8741 if(!type && !emptyParams)
8744 if(methodType && methodType.methodClass)
8745 Compiler_Error($"too many arguments for method %s::%s (%d given, expected %d)\n",
8746 methodType.methodClass.fullName, methodType.method.name, exp.call.arguments->count,
8747 noParams ? 0 : functionType.params.count);
8749 Compiler_Error($"too many arguments for function %s (%d given, expected %d)\n",
8750 name /*exp.call.exp.identifier.string*/, exp.call.arguments->count,
8751 noParams ? 0 : functionType.params.count);
8755 if(methodType && type && type.kind == templateType && type.templateParameter.type == TemplateParameterType::type)
8757 Type templatedType = null;
8758 Class _class = methodType.usedClass;
8759 ClassTemplateParameter curParam = null;
8761 if(_class && _class.templateArgs /*&& _class.templateClass*/)
8764 for(sClass = _class; sClass; sClass = sClass.base)
8766 if(sClass.templateClass) sClass = sClass.templateClass;
8768 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
8770 if(curParam.type == TemplateParameterType::type && !strcmp(type.templateParameter.identifier.string, curParam.name))
8773 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
8775 if(nextClass.templateClass) nextClass = nextClass.templateClass;
8776 id += nextClass.templateParams.count;
8785 if(curParam && _class.templateArgs[id].dataTypeString)
8787 ClassTemplateArgument arg = _class.templateArgs[id];
8789 Context context = SetupTemplatesContext(_class);
8792 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
8793 templatedType = ProcessTypeString(arg.dataTypeString, false);
8794 FinishTemplatesContext(context);
8796 e.destType = templatedType;
8799 templatedType.passAsTemplate = true;
8800 // templatedType.refCount++;
8806 if(type) type.refCount++;
8812 if(type) type.refCount++;
8814 // Don't reach the end for the ellipsis
8815 if(type && type.kind != ellipsisType)
8817 Type next = type.next;
8818 if(!type.refCount) FreeType(type);
8823 if(type && type.kind != ellipsisType)
8825 if(methodType && methodType.methodClass)
8826 Compiler_Warning($"not enough arguments for method %s::%s (%d given, expected %d)\n",
8827 methodType.methodClass.fullName, methodType.method.name, exp.call.arguments ? exp.call.arguments->count : 0,
8828 functionType.params.count + extra);
8830 Compiler_Warning($"not enough arguments for function %s (%d given, expected %d)\n",
8831 name /*exp.call.exp.identifier.string*/, exp.call.arguments ? exp.call.arguments->count : 0,
8832 functionType.params.count + extra);
8835 if(type && !type.refCount) FreeType(type);
8842 kind = TypeKind::functionType;
8845 if(exp.call.exp.type == identifierExp)
8847 char * string = exp.call.exp.identifier.string;
8851 Location oldyylloc = yylloc;
8853 yylloc = exp.call.exp.identifier.loc;
8854 if(strstr(string, "__builtin_") == string);
8856 Compiler_Warning($"%s undefined; assuming extern returning int\n", string);
8857 symbol = Symbol { string = CopyString(string), type = ProcessTypeString("int()", true) };
8858 globalContext.symbols.Add((BTNode)symbol);
8859 if(strstr(symbol.string, "::"))
8860 globalContext.hasNameSpace = true;
8865 else if(exp.call.exp.type == memberExp)
8867 /*Compiler_Warning($"%s undefined; assuming returning int\n",
8868 exp.call.exp.member.member.string);*/
8871 Compiler_Warning($"callable object undefined; extern assuming returning int\n");
8873 if(!functionType.returnType)
8875 functionType.returnType = Type
8882 if(functionType && functionType.kind == TypeKind::functionType)
8884 exp.expType = functionType.returnType;
8886 if(functionType.returnType)
8887 functionType.returnType.refCount++;
8889 if(!functionType.refCount)
8890 FreeType(functionType);
8893 if(exp.call.arguments)
8895 for(e = exp.call.arguments->first; e; e = e.next)
8897 Type destType = e.destType;
8898 ProcessExpressionType(e);
8906 Location oldyylloc = yylloc;
8907 bool thisPtr = (exp.member.exp && exp.member.exp.type == identifierExp && !strcmp(exp.member.exp.identifier.string, "this"));
8908 exp.thisPtr = thisPtr;
8910 // DOING THIS LATER NOW...
8911 if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
8913 exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
8914 /* TODO: Name Space Fix ups
8915 if(!exp.member.member.classSym)
8916 exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.fullName);
8920 ProcessExpressionType(exp.member.exp);
8921 if(exp.member.exp.expType && exp.member.exp.expType.kind == classType && exp.member.exp.expType._class &&
8922 exp.member.exp.expType._class.registered && exp.member.exp.expType._class.registered.type == normalClass)
8924 exp.isConstant = false;
8927 exp.isConstant = exp.member.exp.isConstant;
8928 type = exp.member.exp.expType;
8932 if(type && (type.kind == templateType))
8934 Class _class = thisClass ? thisClass : currentClass;
8935 ClassTemplateParameter param = null;
8938 for(param = _class.templateParams.first; param; param = param.next)
8940 if(param.type == identifier && exp.member.member && exp.member.member.string && !strcmp(param.name, exp.member.member.string))
8944 if(param && param.defaultArg.member)
8946 Expression argExp = GetTemplateArgExpByName(param.name, thisClass, TemplateParameterType::identifier);
8949 Expression expMember = exp.member.exp;
8951 OldList * specs = MkList();
8952 char thisClassTypeString[1024];
8954 FreeIdentifier(exp.member.member);
8956 ProcessExpressionType(argExp);
8959 char * colon = strstr(param.defaultArg.memberString, "::");
8962 char className[1024];
8965 memcpy(thisClassTypeString, param.defaultArg.memberString, colon - param.defaultArg.memberString);
8966 thisClassTypeString[colon - param.defaultArg.memberString] = '\0';
8969 strcpy(thisClassTypeString, _class.fullName);
8972 decl = SpecDeclFromString(param.defaultArg.member.dataTypeString, specs, null);
8974 exp.expType = ProcessType(specs, decl);
8975 if(exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.templateClass)
8977 Class expClass = exp.expType._class.registered;
8978 Class cClass = null;
8983 char templateString[1024];
8984 ClassTemplateParameter param;
8985 sprintf(templateString, "%s<", expClass.templateClass.fullName);
8986 for(cClass = expClass; cClass; cClass = cClass.base)
8989 for(param = cClass.templateParams.first; param; param = param.next)
8993 ClassTemplateArgument arg;
8994 for(sClass = cClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
8995 arg = expClass.templateArgs[id];
8997 for(sClass = _class /*expClass*/; sClass; sClass = sClass.base)
8999 ClassTemplateParameter cParam;
9000 //int p = numParams - sClass.templateParams.count;
9003 for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;
9005 for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next, p++)
9007 if(cParam.type == TemplateParameterType::type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
9009 if(_class.templateArgs && arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9011 arg.dataTypeString = _class.templateArgs[p].dataTypeString;
9012 arg.dataTypeClass = _class.templateArgs[p].dataTypeClass;
9024 strcat(argument, arg.name.string);
9025 strcat(argument, " = ");
9031 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9032 char expString[1024];
9033 OldList * specs = MkList();
9034 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9036 char * string = PrintHexUInt64(arg.expression.ui64);
9037 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9039 ProcessExpressionType(exp);
9040 ComputeExpression(exp);
9041 expString[0] = '\0';
9042 PrintExpression(exp, expString);
9043 strcat(argument, expString);
9045 FreeExpression(exp);
9050 strcat(argument, arg.member.name);
9053 case TemplateParameterType::type:
9055 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9057 if(!strcmp(arg.dataTypeString, "thisclass"))
9058 strcat(argument, thisClassTypeString);
9060 strcat(argument, arg.dataTypeString);
9067 if(paramCount) strcat(templateString, ", ");
9068 if(lastParam != p - 1)
9070 strcat(templateString, param.name);
9071 strcat(templateString, " = ");
9073 strcat(templateString, argument);
9082 int len = strlen(templateString);
9083 if(templateString[len-1] == '>') templateString[len++] = ' ';
9084 templateString[len++] = '>';
9085 templateString[len++] = '\0';
9088 Context context = SetupTemplatesContext(_class);
9089 FreeType(exp.expType);
9090 exp.expType = ProcessTypeString(templateString, false);
9091 FinishTemplatesContext(context);
9095 // *([expType] *)(((byte *)[exp.member.exp]) + [argExp].member.offset)
9096 exp.type = bracketsExp;
9097 exp.list = MkListOne(MkExpOp(null, '*',
9102 MkExpCast(MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl)), MkExpBrackets(MkListOne(MkExpOp(
9103 MkExpBrackets(MkListOne(
9104 MkExpCast(MkTypeName(MkListOne(MkSpecifierName("byte")), MkDeclaratorPointer(MkPointer(null, null), null)), expMember))),
9106 MkExpOp(MkExpMember(MkExpMember(argExp, MkIdentifier("member")), MkIdentifier("offset")),
9108 MkExpMember(MkExpMember(MkExpMember(CopyExpression(argExp), MkIdentifier("member")), MkIdentifier("_class")), MkIdentifier("offset")))))))
9113 else if(type.templateParameter && type.templateParameter.type == TemplateParameterType::type &&
9114 (type.templateParameter.dataType || type.templateParameter.dataTypeString))
9116 type = ProcessTemplateParameterType(type.templateParameter);
9120 if(type && (type.kind == templateType));
9121 else if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9123 Identifier id = exp.member.member;
9124 TypeKind typeKind = type.kind;
9125 Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9126 if(typeKind == subClassType && exp.member.exp.type == classExp)
9128 _class = eSystem_FindClass(privateModule, "ecere::com::Class");
9129 typeKind = classType;
9132 if(id && (typeKind == intType || typeKind == enumType))
9133 _class = eSystem_FindClass(privateModule, "int");
9138 (exp.member.exp.type == identifierExp &&
9139 !strcmp(exp.member.exp.identifier.string, "this"));*/
9140 Property prop = null;
9141 Method method = null;
9142 DataMember member = null;
9143 Property revConvert = null;
9144 ClassProperty classProp = null;
9146 if(id && id._class && id._class.name && !strcmp(id._class.name, "property"))
9147 exp.member.memberType = propertyMember;
9149 if(id && id._class && type._class && !eClass_IsDerived(type._class.registered, _class))
9150 Compiler_Error($"invalid class specifier %s for object of class %s\n", _class.fullName, type._class.string);
9152 if(typeKind != subClassType)
9154 // Prioritize data members over properties for "this"
9155 if((exp.member.memberType == unresolvedMember && thisPtr) || exp.member.memberType == dataMember)
9157 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9158 if(member && member._class != (_class.templateClass ? _class.templateClass : _class) && exp.member.memberType != dataMember)
9160 prop = eClass_FindProperty(_class, id.string, privateModule);
9164 if(!member && !prop)
9165 prop = eClass_FindProperty(_class, id.string, privateModule);
9166 if((member && member._class == (_class.templateClass ? _class.templateClass : _class)) ||
9167 (prop && prop._class == (_class.templateClass ? _class.templateClass : _class)))
9168 exp.member.thisPtr = true;
9170 // Prioritize properties over data members otherwise
9173 // First look for Public Members (Unless class specifier is provided, which skips public priority)
9176 prop = eClass_FindProperty(_class, id.string, null);
9177 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9178 member = eClass_FindDataMember(_class, id.string, null, null, null);
9181 if(!prop && !member)
9183 method = eClass_FindMethod(_class, id.string, null);
9186 prop = eClass_FindProperty(_class, id.string, privateModule);
9187 if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
9188 member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
9194 if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
9201 if(!prop && !member)
9202 method = eClass_FindMethod(_class, id.string, privateModule);
9203 if(!prop && !member && !method)
9205 if(typeKind == subClassType)
9207 classProp = eClass_FindClassProperty(type._class.registered, exp.member.member.string);
9210 exp.member.memberType = classPropertyMember;
9211 exp.expType = ProcessTypeString(classProp.dataTypeString, false);
9215 // Assume this is a class_data member
9216 char structName[1024];
9217 Identifier id = exp.member.member;
9218 Expression classExp = exp.member.exp;
9221 FreeType(classExp.expType);
9222 classExp.expType = ProcessTypeString("ecere::com::Class", false);
9224 strcpy(structName, "__ecereClassData_");
9225 FullClassNameCat(structName, type._class.string, false);
9226 exp.type = pointerExp;
9227 exp.member.member = id;
9229 exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9230 MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
9231 MkExpBrackets(MkListOne(MkExpOp(
9232 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
9233 MkExpMember(classExp, MkIdentifier("data"))), '+',
9234 MkExpMember(MkExpClass(MkListOne(MkSpecifierName(type._class.string)), null), MkIdentifier("offsetClass")))))
9239 ProcessExpressionType(exp);
9245 // Check for reverse conversion
9246 // (Convert in an instantiation later, so that we can use
9247 // deep properties system)
9248 Symbol classSym = FindClass(id.string);
9251 Class convertClass = classSym.registered;
9253 revConvert = eClass_FindProperty(convertClass, _class.fullName, privateModule);
9260 exp.member.memberType = propertyMember;
9262 ProcessPropertyType(prop);
9263 exp.expType = prop.dataType;
9264 if(prop.dataType) prop.dataType.refCount++;
9268 if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9270 FreeExpContents(exp);
9271 exp.type = identifierExp;
9272 exp.identifier = MkIdentifier("class");
9273 ProcessExpressionType(exp);
9277 exp.member.memberType = dataMember;
9278 DeclareStruct(_class.fullName, false);
9279 if(!member.dataType)
9281 Context context = SetupTemplatesContext(_class);
9282 member.dataType = ProcessTypeString(member.dataTypeString, false);
9283 FinishTemplatesContext(context);
9285 exp.expType = member.dataType;
9286 if(member.dataType) member.dataType.refCount++;
9290 exp.member.memberType = reverseConversionMember;
9291 exp.expType = MkClassType(revConvert._class.fullName);
9299 exp.type = identifierExp;
9300 exp.identifier = exp.member.member;
9303 exp.member.memberType = methodMember;
9305 if(!method.dataType)
9306 ProcessMethodType(method);
9314 // Tricky spot here... To use instance versus class virtual table
9315 // Put it back to what it was... What did we break?
9317 // Had to put it back for overriding Main of Thread global instance
9319 //exp.expType.methodClass = _class;
9320 exp.expType.methodClass = (id && id._class) ? _class : null;
9322 // Need the actual class used for templated classes
9323 exp.expType.usedClass = _class;
9327 if(exp.member.exp.expType.classObjectType == typedObject && !strcmp(exp.member.member.string, "_class"))
9329 FreeExpContents(exp);
9330 exp.type = identifierExp;
9331 exp.identifier = MkIdentifier("class");
9332 ProcessExpressionType(exp);
9335 yylloc = exp.member.member.loc;
9336 Compiler_Error($"couldn't find member %s in class %s\n", id.string, _class.fullName);
9338 eClass_AddDataMember(_class, id.string, "int", 0, 0, publicAccess);
9341 if(_class && /*(_class.templateClass || _class.templateArgs) && */exp.expType)
9346 while(tClass && !tClass.templateClass) tClass = tClass.base;
9348 if(tClass && exp.expType.kind == templateType && exp.expType.templateParameter.type == TemplateParameterType::type)
9351 ClassTemplateParameter curParam = null;
9354 for(sClass = tClass; sClass; sClass = sClass.base)
9357 if(sClass.templateClass) sClass = sClass.templateClass;
9358 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9360 if(curParam.type == TemplateParameterType::type && !strcmp(exp.expType.templateParameter.identifier.string, curParam.name))
9362 for(sClass = sClass.base; sClass; sClass = sClass.base)
9363 id += sClass.templateParams.count;
9371 if(curParam && tClass.templateArgs[id].dataTypeString)
9373 ClassTemplateArgument arg = tClass.templateArgs[id];
9374 Context context = SetupTemplatesContext(tClass);
9376 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9377 FreeType(exp.expType);
9378 exp.expType = ProcessTypeString(arg.dataTypeString, false);
9381 if(exp.expType.kind == thisClassType)
9383 FreeType(exp.expType);
9384 exp.expType = ReplaceThisClassType(_class);
9387 if(tClass.templateClass)
9388 exp.expType.passAsTemplate = true;
9389 //exp.expType.refCount++;
9392 exp.destType = ProcessTypeString(arg.dataTypeString, false);
9393 //exp.destType.refCount++;
9395 if(exp.destType.kind == thisClassType)
9397 FreeType(exp.destType);
9398 exp.destType = ReplaceThisClassType(_class);
9402 FinishTemplatesContext(context);
9405 // TODO: MORE GENERIC SUPPORT FOR DEEPER TYPES
9406 else if(tClass && exp.expType.kind == pointerType && exp.expType.type && exp.expType.type.kind == templateType && exp.expType.type.templateParameter.type == TemplateParameterType::type)
9409 ClassTemplateParameter curParam = null;
9412 for(sClass = tClass; sClass; sClass = sClass.base)
9415 if(sClass.templateClass) sClass = sClass.templateClass;
9416 for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
9418 if(curParam.type == TemplateParameterType::type &&
9419 !strcmp(exp.expType.type.templateParameter.identifier.string, curParam.name))
9421 for(sClass = sClass.base; sClass; sClass = sClass.base)
9422 id += sClass.templateParams.count;
9432 ClassTemplateArgument arg = tClass.templateArgs[id];
9433 Context context = SetupTemplatesContext(tClass);
9436 arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
9438 basicType = ProcessTypeString(arg.dataTypeString, false);
9441 if(basicType.kind == thisClassType)
9443 FreeType(basicType);
9444 basicType = ReplaceThisClassType(_class);
9447 /* DO WE REALLY WANT THIS HERE? IT SEEMS TO BE ONLY USED WITH Array::array which was causing bug 135
9448 if(tClass.templateClass)
9449 basicType.passAsTemplate = true;
9452 FreeType(exp.expType);
9454 exp.expType = Type { refCount = 1, kind = pointerType, type = basicType };
9455 //exp.expType.refCount++;
9458 exp.destType = exp.expType;
9459 exp.destType.refCount++;
9463 Expression newExp { };
9464 OldList * specs = MkList();
9466 decl = SpecDeclFromString(arg.dataTypeString, specs, null);
9468 if(exp.destType) exp.destType.refCount++;
9469 if(exp.expType) exp.expType.refCount++;
9471 exp.cast.typeName = MkTypeName(specs, MkDeclaratorPointer(MkPointer(null, null), decl));
9472 exp.cast.exp = newExp;
9473 //FreeType(exp.expType);
9474 //exp.expType = null;
9475 //ProcessExpressionType(sourceExp);
9478 FinishTemplatesContext(context);
9481 else if(tClass && exp.expType.kind == classType && exp.expType._class && strchr(exp.expType._class.string, '<'))
9483 Class expClass = exp.expType._class.registered;
9486 Class cClass = null;
9491 char templateString[1024];
9492 ClassTemplateParameter param;
9493 sprintf(templateString, "%s<", expClass.templateClass.fullName);
9494 while(cClass != expClass)
9497 for(sClass = expClass; sClass && sClass.base != cClass; sClass = sClass.base);
9500 for(param = cClass.templateParams.first; param; param = param.next)
9502 Class cClassCur = null;
9505 ClassTemplateParameter paramCur = null;
9506 ClassTemplateArgument arg;
9507 while(cClassCur != tClass && !paramCur)
9510 for(sClassCur = tClass; sClassCur && sClassCur.base != cClassCur; sClassCur = sClassCur.base);
9511 cClassCur = sClassCur;
9513 for(paramCur = cClassCur.templateParams.first; paramCur; paramCur = paramCur.next)
9515 if(!strcmp(paramCur.name, param.name))
9523 if(paramCur && paramCur.type == TemplateParameterType::type)
9524 arg = tClass.templateArgs[cp];
9526 arg = expClass.templateArgs[p];
9533 strcat(argument, arg.name.string);
9534 strcat(argument, " = ");
9540 // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
9541 char expString[1024];
9542 OldList * specs = MkList();
9543 Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
9545 char * string = PrintHexUInt64(arg.expression.ui64);
9546 exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
9548 ProcessExpressionType(exp);
9549 ComputeExpression(exp);
9550 expString[0] = '\0';
9551 PrintExpression(exp, expString);
9552 strcat(argument, expString);
9554 FreeExpression(exp);
9559 strcat(argument, arg.member.name);
9562 case TemplateParameterType::type:
9564 if(arg.dataTypeString && (!param.defaultArg.dataTypeString || strcmp(arg.dataTypeString, param.defaultArg.dataTypeString)))
9565 strcat(argument, arg.dataTypeString);
9571 if(paramCount) strcat(templateString, ", ");
9572 if(lastParam != p - 1)
9574 strcat(templateString, param.name);
9575 strcat(templateString, " = ");
9577 strcat(templateString, argument);
9586 int len = strlen(templateString);
9587 if(templateString[len-1] == '>') templateString[len++] = ' ';
9588 templateString[len++] = '>';
9589 templateString[len++] = '\0';
9592 FreeType(exp.expType);
9594 Context context = SetupTemplatesContext(tClass);
9595 exp.expType = ProcessTypeString(templateString, false);
9596 FinishTemplatesContext(context);
9603 Compiler_Error($"undefined class %s\n", (id && (!id._class || id._class.name))? (id.classSym ? id.classSym.string : (type._class ? type._class.string : null)) : "(null)");
9605 else if(type && (type.kind == structType || type.kind == unionType))
9607 Type memberType = exp.member.member ? FindMember(type, exp.member.member.string) : null;
9610 exp.expType = memberType;
9612 memberType.refCount++;
9617 char expString[10240];
9618 expString[0] = '\0';
9619 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
9620 Compiler_Error($"member operator on non-structure type expression %s\n", expString);
9623 if(exp.expType && exp.expType.kind == thisClassType && (!exp.destType || exp.destType.kind != thisClassType))
9625 if(type && (type.kind == classType || type.kind == subClassType || type.kind == intType || type.kind == enumType))
9627 Identifier id = exp.member.member;
9628 Class _class = (id && (!id._class || id._class.name))? ( id.classSym ? id.classSym.registered : (type._class ? type._class.registered : null)) : null;
9631 FreeType(exp.expType);
9632 exp.expType = ReplaceThisClassType(_class);
9639 // Convert x->y into (*x).y
9642 Type destType = exp.destType;
9644 // DOING THIS LATER NOW...
9645 if(exp.member.member && exp.member.member._class && exp.member.member._class.name)
9647 exp.member.member.classSym = exp.member.member._class.symbol; // FindClass(exp.member.member._class.name);
9648 /* TODO: Name Space Fix ups
9649 if(!exp.member.member.classSym)
9650 exp.member.member.nameSpace = eSystem_FindNameSpace(privateModule, exp.member.member._class.name);
9654 exp.member.exp = MkExpBrackets(MkListOne(MkExpOp(null, '*', exp.member.exp)));
9655 exp.type = memberExp;
9658 ProcessExpressionType(exp);
9665 //ComputeExpression(exp);
9667 Symbol classSym = exp._class.symbol; // FindClass(exp._class.name);
9668 if(classSym && classSym.registered)
9670 if(classSym.registered.type == noHeadClass)
9674 DeclareStruct(classSym.string, false);
9675 FreeSpecifier(exp._class);
9676 exp.type = typeSizeExp;
9677 FullClassNameCat(name, classSym.string, false);
9678 exp.typeName = MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(name), null)), null);
9682 if(classSym.registered.fixed)
9684 FreeSpecifier(exp._class);
9685 exp.constant = PrintUInt(classSym.registered.templateClass ? classSym.registered.templateClass.structSize : classSym.registered.structSize);
9686 exp.type = constantExp;
9690 char className[1024];
9691 strcpy(className, "__ecereClass_");
9692 FullClassNameCat(className, classSym.string, true);
9693 MangleClassName(className);
9695 DeclareClass(classSym, className);
9697 FreeExpContents(exp);
9698 exp.type = pointerExp;
9699 exp.member.exp = MkExpIdentifier(MkIdentifier(className));
9700 exp.member.member = MkIdentifier("structSize");
9710 // exp.isConstant = true;
9715 Type type = ProcessType(exp.typeName.qualifiers, exp.typeName.declarator);
9722 exp.isConstant = true;
9724 DeclareType(type, false, false);
9730 Type type = ProcessType(exp.cast.typeName.qualifiers, exp.cast.typeName.declarator);
9732 FreeType(exp.cast.exp.destType);
9733 exp.cast.exp.destType = type;
9735 ProcessExpressionType(exp.cast.exp);
9740 // if(!NeedCast(exp.cast.exp.expType, exp.cast.exp.destType))
9741 if(!exp.cast.exp.needCast && !NeedCast(exp.cast.exp.expType, type))
9743 void * prev = exp.prev, * next = exp.next;
9744 Type expType = exp.cast.exp.destType;
9745 Expression castExp = exp.cast.exp;
9746 Type destType = exp.destType;
9748 if(expType) expType.refCount++;
9750 //FreeType(exp.destType);
9751 FreeType(exp.expType);
9752 FreeTypeName(exp.cast.typeName);
9755 FreeType(exp.expType);
9756 FreeType(exp.destType);
9758 exp.expType = expType;
9759 exp.destType = destType;
9769 exp.isConstant = exp.cast.exp.isConstant;
9774 case extensionInitializerExp:
9776 Type type = ProcessType(exp.initializer.typeName.qualifiers, exp.initializer.typeName.declarator);
9779 // We have yet to support this... ( { } initializers are currently processed inside ProcessDeclaration()'s initDeclaration case statement
9780 // ProcessInitializer(exp.initializer.initializer, type);
9786 Type type = ProcessType(exp.vaArg.typeName.qualifiers, exp.vaArg.typeName.declarator);
9787 ProcessExpressionType(exp.vaArg.exp);
9795 exp.isConstant = true;
9797 FreeType(exp.cond.cond.destType);
9798 exp.cond.cond.destType = MkClassType("bool");
9799 exp.cond.cond.destType.truth = true;
9800 ProcessExpressionType(exp.cond.cond);
9801 if(!exp.cond.cond.isConstant)
9802 exp.isConstant = false;
9803 for(e = exp.cond.exp->first; e; e = e.next)
9807 FreeType(e.destType);
9808 e.destType = exp.destType;
9809 if(e.destType) e.destType.refCount++;
9811 ProcessExpressionType(e);
9814 exp.expType = e.expType;
9815 if(e.expType) e.expType.refCount++;
9818 exp.isConstant = false;
9821 FreeType(exp.cond.elseExp.destType);
9822 // Added this check if we failed to find an expType
9823 // exp.cond.elseExp.destType = exp.expType ? exp.expType : exp.destType;
9826 exp.cond.elseExp.destType = exp.destType ? exp.destType : exp.expType;
9828 if(exp.cond.elseExp.destType)
9829 exp.cond.elseExp.destType.refCount++;
9830 ProcessExpressionType(exp.cond.elseExp);
9832 // FIXED THIS: Was done before calling process on elseExp
9833 if(!exp.cond.elseExp.isConstant)
9834 exp.isConstant = false;
9837 case extensionCompoundExp:
9839 if(exp.compound && exp.compound.compound.statements && exp.compound.compound.statements->last)
9841 Statement last = exp.compound.compound.statements->last;
9842 if(last.type == expressionStmt && last.expressions && last.expressions->last)
9844 ((Expression)last.expressions->last).destType = exp.destType;
9846 exp.destType.refCount++;
9848 ProcessStatement(exp.compound);
9849 exp.expType = ((Expression)last.expressions->last).expType;
9850 if(((Expression)last.expressions->last).expType)
9851 exp.expType.refCount++;
9857 Specifier spec = exp._classExp.specifiers->first;
9858 if(spec && spec.type == nameSpecifier)
9860 exp.expType = MkClassType(spec.name);
9861 exp.expType.kind = subClassType;
9862 exp.byReference = true;
9866 exp.expType = MkClassType("ecere::com::Class");
9867 exp.byReference = true;
9873 Class _class = thisClass ? thisClass : currentClass;
9876 Identifier id = exp.classData.id;
9877 char structName[1024];
9878 Expression classExp;
9879 strcpy(structName, "__ecereClassData_");
9880 FullClassNameCat(structName, _class.fullName, false);
9881 exp.type = pointerExp;
9882 exp.member.member = id;
9883 if(curCompound && FindSymbol("this", curContext, curCompound.compound.context, false, false))
9884 classExp = MkExpMember(MkExpIdentifier(MkIdentifier("this")), MkIdentifier("_class"));
9886 classExp = MkExpIdentifier(MkIdentifier("class"));
9888 exp.member.exp = MkExpBrackets(MkListOne(MkExpCast(
9889 MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)),
9890 MkExpBrackets(MkListOne(MkExpOp(
9891 MkExpCast(MkTypeName(MkListOne(MkSpecifier(CHAR)), MkDeclaratorPointer(MkPointer(null,null), null)),
9892 MkExpMember(classExp, MkIdentifier("data"))), '+',
9893 MkExpMember(MkExpClass(MkListOne(MkSpecifierName(_class.fullName)), null), MkIdentifier("offsetClass")))))
9896 ProcessExpressionType(exp);
9904 char * typeString = null;
9905 char typeStringBuf[1024];
9906 if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
9907 exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
9909 Class templateClass = exp.destType._class.registered;
9910 typeString = templateClass.templateArgs[2].dataTypeString;
9914 // Guess type from expressions in the array
9916 for(e = exp.list->first; e; e = e.next)
9918 ProcessExpressionType(e);
9921 if(!type) { type = e.expType; type.refCount++; }
9924 // if(!MatchType(e.expType, type, null, null, null, false, false, false))
9925 if(!MatchTypeExpression(e, type, null, false))
9931 e = exp.list->first;
9932 ProcessExpressionType(e);
9935 //if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
9936 if(!MatchTypeExpression(e, type, null, false))
9938 FreeType(e.expType);
9949 FreeType(e.expType);
9956 typeStringBuf[0] = '\0';
9957 PrintType(type, typeStringBuf, false, true);
9958 typeString = typeStringBuf;
9966 (Container)& (struct BuiltInContainer)
9968 ._vTbl = class(BuiltInContainer)._vTbl,
9969 ._class = class(BuiltInContainer),
9971 .data = (int[]){ 1, 7, 3, 4, 5 },
9976 char templateString[1024];
9977 OldList * initializers = MkList();
9978 OldList * structInitializers = MkList();
9979 OldList * specs = MkList();
9981 Declarator decl = SpecDeclFromString(typeString, specs, null);
9982 sprintf(templateString, "Container<%s>", typeString);
9987 type = ProcessTypeString(typeString, false);
9988 while(e = exp.list->first)
9990 exp.list->Remove(e);
9993 ProcessExpressionType(e);
9994 ListAdd(initializers, MkInitializerAssignment(e));
10000 DeclareStruct("ecere::com::BuiltInContainer", false);
10002 ListAdd(structInitializers, /*MkIdentifier("_vTbl")*/ MkInitializerAssignment(MkExpMember(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null), MkIdentifier("_vTbl"))));
10003 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10004 ListAdd(structInitializers, /*MkIdentifier("_class")*/ MkInitializerAssignment(MkExpClass(MkListOne(MkSpecifierName("BuiltInContainer")), null)));
10005 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10006 ListAdd(structInitializers, /*MkIdentifier("_refCount")*/MkInitializerAssignment(MkExpConstant("0")));
10007 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10008 ListAdd(structInitializers, /*MkIdentifier("data")*/ MkInitializerAssignment(MkExpExtensionInitializer(
10009 MkTypeName(specs, MkDeclaratorArray(decl, null)),
10010 MkInitializerList(initializers))));
10011 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10012 ListAdd(structInitializers, /*MkIdentifier("count")*/ MkInitializerAssignment({ type = constantExp, constant = PrintString(initializers->count) }));
10013 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10014 ListAdd(structInitializers, /*MkIdentifier("type")*/ MkInitializerAssignment(MkExpClass(CopyList(specs, CopySpecifier), CopyDeclarator(decl))));
10015 ProcessExpressionType(((Initializer)structInitializers->last).exp);
10016 exp.expType = ProcessTypeString(templateString, false);
10017 exp.type = bracketsExp;
10018 exp.list = MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName(templateString)), null),
10020 expExt = MkExpExtensionInitializer(MkTypeName(MkListOne(MkSpecifierName("BuiltInContainer")), null),
10021 MkInitializerList(structInitializers)))));
10022 ProcessExpressionType(expExt);
10026 exp.expType = ProcessTypeString("Container", false);
10027 Compiler_Error($"Couldn't determine type of array elements\n");
10033 if(exp.expType && exp.expType.kind == thisClassType && thisClass && (!exp.destType || exp.destType.kind != thisClassType))
10035 FreeType(exp.expType);
10036 exp.expType = ReplaceThisClassType(thisClass);
10039 // Resolve structures here
10040 if(exp.expType && (exp.expType.kind == structType || exp.expType.kind == unionType || exp.expType.kind == enumType) && !exp.expType.members.first && exp.expType.enumName)
10042 Symbol symbol = FindSymbol(exp.expType.enumName, curContext, globalContext, true, false);
10043 // TODO: Fix members reference...
10046 if(exp.expType.kind != enumType)
10049 String enumName = CopyString(exp.expType.enumName);
10051 // Fixed a memory leak on self-referencing C structs typedefs
10052 // by instantiating a new type rather than simply copying members
10053 // into exp.expType
10054 FreeType(exp.expType);
10055 exp.expType = Type { };
10056 exp.expType.kind = symbol.type.kind;
10057 exp.expType.refCount++;
10058 exp.expType.enumName = enumName;
10060 exp.expType.members = symbol.type.members;
10061 for(member = symbol.type.members.first; member; member = member.next)
10067 for(member = symbol.type.members.first; member; member = member.next)
10069 NamedLink value { name = CopyString(member.name) };
10070 exp.expType.members.Add(value);
10077 if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
10078 else if(exp.destType && !exp.destType.keepCast)
10080 if(!CheckExpressionType(exp, exp.destType, false))
10082 if(!exp.destType.count || unresolved)
10087 if(exp.destType.kind != ellipsisType)
10093 char expString[10240];
10094 expString[0] = '\0';
10096 PrintType(exp.destType, type2, false, true);
10098 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10100 Compiler_Error($"unresolved identifier %s; expected %s\n", expString, type2);
10101 else if(exp.type != dummyExp)
10102 Compiler_Error($"couldn't determine type of %s; expected %s\n", expString, type2);
10107 char expString[10240] ;
10108 expString[0] = '\0';
10109 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10112 Compiler_Error($"unresolved identifier %s\n", expString);
10113 else if(exp.type != dummyExp)
10114 Compiler_Error($"couldn't determine type of %s\n", expString);
10125 PrintType(exp.expType, type1, false, true);
10126 PrintType(exp.destType, type2, false, true);
10129 //CheckExpressionType(exp, exp.destType, false);
10131 if(exp.destType.truth && exp.destType._class && exp.destType._class.registered && !strcmp(exp.destType._class.registered.name, "bool") &&
10132 exp.expType.kind != voidType && exp.expType.kind != structType && exp.expType.kind != unionType &&
10133 (exp.expType.kind != classType || exp.expType.classObjectType || (exp.expType._class && exp.expType._class.registered && exp.expType._class.registered.type != structClass)));
10136 char expString[10240];
10137 expString[0] = '\0';
10138 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10141 CheckExpressionType(exp, exp.destType, false);
10143 // Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
10144 if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
10145 Compiler_Warning($"incompatible expression %s (%s); expected %s\n", expString, type1, type2);
10147 // TO CHECK: FORCING HERE TO HELP DEBUGGER
10148 FreeType(exp.expType);
10149 exp.destType.refCount++;
10150 exp.expType = exp.destType;
10155 else if(exp.destType && exp.destType.kind == ellipsisType && exp.expType && exp.expType.passAsTemplate)
10157 Expression newExp { };
10158 char typeString[1024];
10159 OldList * specs = MkList();
10162 typeString[0] = '\0';
10166 if(exp.expType) exp.expType.refCount++;
10167 if(exp.expType) exp.expType.refCount++;
10168 exp.type = castExp;
10169 newExp.destType = exp.expType;
10171 PrintType(exp.expType, typeString, false, false);
10172 decl = SpecDeclFromString(typeString, specs, null);
10174 exp.cast.typeName = MkTypeName(specs, decl);
10175 exp.cast.exp = newExp;
10178 else if(unresolved)
10180 if(exp.identifier._class && exp.identifier._class.name)
10181 Compiler_Error($"unresolved identifier %s::%s\n", exp.identifier._class.name, exp.identifier.string);
10182 else if(exp.identifier.string && exp.identifier.string[0])
10183 Compiler_Error($"unresolved identifier %s\n", exp.identifier.string);
10185 else if(!exp.expType && exp.type != dummyExp)
10187 char expString[10240];
10188 expString[0] = '\0';
10189 if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
10190 Compiler_Error($"couldn't determine type of %s\n", expString);
10193 // Let's try to support any_object & typed_object here:
10194 ApplyAnyObjectLogic(exp);
10196 if(!notByReference && exp.expType && exp.expType.kind == classType && exp.expType._class && exp.expType._class.registered &&
10197 exp.expType._class.registered.type == noHeadClass)
10199 exp.byReference = true;
10201 /*else if(!notByReference && exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
10202 exp.destType._class.registered.type == noHeadClass)
10204 exp.byReference = true;
10206 yylloc = oldyylloc;
10209 static void FindNextDataMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
10211 // THIS CODE WILL FIND NEXT MEMBER...
10214 *curMember = (*curMember).next;
10216 if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
10218 *curMember = subMemberStack[--(*subMemberStackPos)];
10219 *curMember = (*curMember).next;
10222 // SKIP ALL PROPERTIES HERE...
10223 while((*curMember) && (*curMember).isProperty)
10224 *curMember = (*curMember).next;
10226 if(subMemberStackPos)
10228 while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10230 subMemberStack[(*subMemberStackPos)++] = *curMember;
10232 *curMember = (*curMember).members.first;
10233 while(*curMember && (*curMember).isProperty)
10234 *curMember = (*curMember).next;
10242 if(subMemberStackPos && *subMemberStackPos)
10244 *curMember = subMemberStack[--(*subMemberStackPos)];
10245 *curMember = (*curMember).next;
10249 Class lastCurClass = *curClass;
10251 if(*curClass == _class) break; // REACHED THE END
10253 for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass; *curClass = (*curClass).base);
10254 *curMember = (*curClass).membersAndProperties.first;
10257 while((*curMember) && (*curMember).isProperty)
10258 *curMember = (*curMember).next;
10259 if(subMemberStackPos)
10261 while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
10263 subMemberStack[(*subMemberStackPos)++] = *curMember;
10265 *curMember = (*curMember).members.first;
10266 while(*curMember && (*curMember).isProperty)
10267 *curMember = (*curMember).next;
10275 static void ProcessInitializer(Initializer init, Type type)
10279 case expInitializer:
10280 if(!init.exp || init.exp.type != instanceExp || !init.exp.instance || init.exp.instance._class || !type || type.kind == classType)
10282 // TESTING THIS FOR SHUTTING = 0 WARNING
10283 if(init.exp && !init.exp.destType)
10285 FreeType(init.exp.destType);
10286 init.exp.destType = type;
10287 if(type) type.refCount++;
10291 ProcessExpressionType(init.exp);
10292 init.isConstant = init.exp.isConstant;
10298 Expression exp = init.exp;
10299 Instantiation inst = exp.instance;
10300 MembersInit members;
10302 init.type = listInitializer;
10303 init.list = MkList();
10307 for(members = inst.members->first; members; members = members.next)
10309 if(members.type == dataMembersInit)
10312 for(member = members.dataMembers->first; member; member = member.next)
10314 ListAdd(init.list, member.initializer);
10315 member.initializer = null;
10318 // Discard all MembersInitMethod
10321 FreeExpression(exp);
10323 case listInitializer:
10326 Type initializerType = null;
10327 Class curClass = null;
10328 DataMember curMember = null;
10329 DataMember subMemberStack[256];
10330 int subMemberStackPos = 0;
10332 if(type && type.kind == arrayType)
10333 initializerType = Dereference(type);
10334 else if(type && (type.kind == structType || type.kind == unionType))
10335 initializerType = type.members.first;
10337 for(i = init.list->first; i; i = i.next)
10339 if(type && type.kind == classType && type._class && type._class.registered)
10341 // 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)
10342 FindNextDataMember(type._class.registered, &curClass, &curMember, subMemberStack, &subMemberStackPos);
10343 // TODO: Generate error on initializing a private data member this way from another module...
10346 if(!curMember.dataType)
10347 curMember.dataType = ProcessTypeString(curMember.dataTypeString, false);
10348 initializerType = curMember.dataType;
10351 ProcessInitializer(i, initializerType);
10352 if(initializerType && type && (type.kind == structType || type.kind == unionType))
10353 initializerType = initializerType.next;
10355 init.isConstant = false;
10358 if(type && type.kind == arrayType)
10359 FreeType(initializerType);
10361 if(type && type.kind != arrayType && type.kind != structType && type.kind != unionType && (type.kind != classType || !type._class.registered || type._class.registered.type != structClass))
10363 Compiler_Error($"Assigning list initializer to non list\n");
10370 static void ProcessSpecifier(Specifier spec, bool declareStruct)
10374 case baseSpecifier:
10376 if(spec.specifier == THISCLASS)
10380 spec.type = nameSpecifier;
10381 spec.name = ReplaceThisClass(thisClass);
10382 spec.symbol = FindClass(spec.name);
10383 ProcessSpecifier(spec, declareStruct);
10388 case nameSpecifier:
10390 Symbol symbol = FindType(curContext, spec.name);
10392 DeclareType(symbol.type, true, true);
10393 else if((symbol = spec.symbol /*FindClass(spec.name)*/) && symbol.registered && symbol.registered.type == structClass && declareStruct)
10394 DeclareStruct(spec.name, false);
10397 case enumSpecifier:
10402 for(e = spec.list->first; e; e = e.next)
10405 ProcessExpressionType(e.exp);
10410 case structSpecifier:
10411 case unionSpecifier:
10413 if(spec.definitions)
10416 Symbol symbol = spec.id ? FindClass(spec.id.string) : null;
10418 ProcessClass(spec.definitions, symbol);
10421 for(def = spec.definitions->first; def; def = def.next)
10423 //if(def.type == declarationClassDef && def.decl && def.decl.type == DeclarationStruct)
10424 ProcessDeclaration(def.decl);
10431 case classSpecifier:
10433 Symbol classSym = FindClass(spec.name);
10434 if(classSym && classSym.registered && classSym.registered.type == structClass)
10435 DeclareStruct(spec.name, false);
10443 static void ProcessDeclarator(Declarator decl)
10447 case identifierDeclarator:
10448 if(decl.identifier.classSym /* TODO: Name Space Fix ups || decl.identifier.nameSpace*/)
10450 FreeSpecifier(decl.identifier._class);
10451 decl.identifier._class = null;
10454 case arrayDeclarator:
10456 ProcessExpressionType(decl.array.exp);
10457 case structDeclarator:
10458 case bracketsDeclarator:
10459 case functionDeclarator:
10460 case pointerDeclarator:
10461 case extendedDeclarator:
10462 case extendedDeclaratorEnd:
10463 if(decl.declarator)
10464 ProcessDeclarator(decl.declarator);
10465 if(decl.type == functionDeclarator)
10467 Identifier id = GetDeclId(decl);
10468 if(id && id._class)
10472 qualifiers = MkListOne(id._class);
10475 if(!decl.function.parameters)
10476 decl.function.parameters = MkList();
10477 decl.function.parameters->Insert(null, param);
10480 if(decl.function.parameters)
10484 for(param = decl.function.parameters->first; param; param = param.next)
10486 if(param.qualifiers && param.qualifiers->first)
10488 Specifier spec = param.qualifiers->first;
10489 if(spec && spec.specifier == TYPED_OBJECT)
10491 Declarator d = param.declarator;
10494 qualifiers = MkListOne(MkSpecifier(VOID));
10495 declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10498 FreeList(param.qualifiers, FreeSpecifier);
10500 param.qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
10501 param.declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
10503 decl.function.parameters->Insert(param, newParam);
10506 else if(spec && spec.specifier == ANY_OBJECT)
10508 Declarator d = param.declarator;
10510 FreeList(param.qualifiers, FreeSpecifier);
10512 param.qualifiers = MkListOne(MkSpecifier(VOID));
10513 param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
10515 else if(spec.specifier == THISCLASS)
10519 spec.type = nameSpecifier;
10520 spec.name = ReplaceThisClass(thisClass);
10521 spec.symbol = FindClass(spec.name);
10522 ProcessSpecifier(spec, false);
10527 if(param.declarator)
10528 ProcessDeclarator(param.declarator);
10536 static void ProcessDeclaration(Declaration decl)
10541 case initDeclaration:
10543 bool declareStruct = false;
10545 lineNum = decl.pos.line;
10546 column = decl.pos.col;
10549 if(decl.declarators)
10553 for(d = decl.declarators->first; d; d = d.next)
10555 Type type, subType;
10556 ProcessDeclarator(d.declarator);
10558 type = ProcessType(decl.specifiers, d.declarator);
10562 ProcessInitializer(d.initializer, type);
10564 // Change "ColorRGB a = ColorRGB { 1,2,3 } => ColorRGB a { 1,2,3 }
10566 if(decl.declarators->count == 1 && d.initializer.type == expInitializer &&
10567 d.initializer.exp.type == instanceExp)
10569 if(type.kind == classType && type._class ==
10570 d.initializer.exp.expType._class)
10572 Instantiation inst = d.initializer.exp.instance;
10573 inst.exp = MkExpIdentifier(CopyIdentifier(GetDeclId(d.declarator)));
10575 d.initializer.exp.instance = null;
10576 if(decl.specifiers)
10577 FreeList(decl.specifiers, FreeSpecifier);
10578 FreeList(decl.declarators, FreeInitDeclarator);
10582 decl.type = instDeclaration;
10587 for(subType = type; subType;)
10589 if(subType.kind == classType)
10591 declareStruct = true;
10594 else if(subType.kind == pointerType)
10596 else if(subType.kind == arrayType)
10597 subType = subType.arrayType;
10607 if(decl.specifiers)
10610 for(s = decl.specifiers->first; s; s = s.next)
10612 ProcessSpecifier(s, declareStruct);
10617 case instDeclaration:
10619 ProcessInstantiationType(decl.inst);
10622 case structDeclaration:
10626 bool declareStruct = false;
10628 if(decl.declarators)
10630 for(d = decl.declarators->first; d; d = d.next)
10632 Type type = ProcessType(decl.specifiers, d.declarator);
10634 ProcessDeclarator(d);
10635 for(subType = type; subType;)
10637 if(subType.kind == classType)
10639 declareStruct = true;
10642 else if(subType.kind == pointerType)
10644 else if(subType.kind == arrayType)
10645 subType = subType.arrayType;
10652 if(decl.specifiers)
10654 for(spec = decl.specifiers->first; spec; spec = spec.next)
10655 ProcessSpecifier(spec, declareStruct);
10662 static FunctionDefinition curFunction;
10664 static void CreateFireWatcher(Property prop, Expression object, Statement stmt)
10666 char propName[1024], propNameM[1024];
10667 char getName[1024], setName[1024];
10670 DeclareProperty(prop, setName, getName);
10672 // eInstance_FireWatchers(object, prop);
10673 strcpy(propName, "__ecereProp_");
10674 FullClassNameCat(propName, prop._class.fullName, false);
10675 strcat(propName, "_");
10676 // strcat(propName, prop.name);
10677 FullClassNameCat(propName, prop.name, true);
10678 MangleClassName(propName);
10680 strcpy(propNameM, "__ecerePropM_");
10681 FullClassNameCat(propNameM, prop._class.fullName, false);
10682 strcat(propNameM, "_");
10683 // strcat(propNameM, prop.name);
10684 FullClassNameCat(propNameM, prop.name, true);
10685 MangleClassName(propNameM);
10687 if(prop.isWatchable)
10690 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10691 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10692 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10695 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10696 ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10697 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireWatchers")), args));
10703 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10704 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
10705 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10708 ListAdd(args, object ? CopyExpression(object) : MkExpIdentifier(MkIdentifier("this")));
10709 ListAdd(args, MkExpIdentifier(MkIdentifier(propNameM)));
10710 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_FireSelfWatchers")), args));
10713 if(curFunction.propSet && !strcmp(curFunction.propSet.string, prop.name) &&
10714 (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
10715 curFunction.propSet.fireWatchersDone = true;
10718 static void ProcessStatement(Statement stmt)
10722 lineNum = stmt.pos.line;
10723 column = stmt.pos.col;
10728 ProcessStatement(stmt.labeled.stmt);
10731 // This expression should be constant...
10732 if(stmt.caseStmt.exp)
10734 FreeType(stmt.caseStmt.exp.destType);
10735 stmt.caseStmt.exp.destType = curSwitchType;
10736 if(curSwitchType) curSwitchType.refCount++;
10737 ProcessExpressionType(stmt.caseStmt.exp);
10738 ComputeExpression(stmt.caseStmt.exp);
10740 if(stmt.caseStmt.stmt)
10741 ProcessStatement(stmt.caseStmt.stmt);
10745 if(stmt.compound.context)
10750 Statement prevCompound = curCompound;
10751 Context prevContext = curContext;
10753 if(!stmt.compound.isSwitch)
10755 curCompound = stmt;
10756 curContext = stmt.compound.context;
10759 if(stmt.compound.declarations)
10761 for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
10762 ProcessDeclaration(decl);
10764 if(stmt.compound.statements)
10766 for(s = stmt.compound.statements->first; s; s = s.next)
10767 ProcessStatement(s);
10770 curContext = prevContext;
10771 curCompound = prevCompound;
10775 case expressionStmt:
10778 if(stmt.expressions)
10780 for(exp = stmt.expressions->first; exp; exp = exp.next)
10781 ProcessExpressionType(exp);
10789 FreeType(((Expression)stmt.ifStmt.exp->last).destType);
10790 ((Expression)stmt.ifStmt.exp->last).destType = MkClassType("bool");
10791 ((Expression)stmt.ifStmt.exp->last).destType.truth = true;
10792 for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
10794 ProcessExpressionType(exp);
10796 if(stmt.ifStmt.stmt)
10797 ProcessStatement(stmt.ifStmt.stmt);
10798 if(stmt.ifStmt.elseStmt)
10799 ProcessStatement(stmt.ifStmt.elseStmt);
10804 Type oldSwitchType = curSwitchType;
10805 if(stmt.switchStmt.exp)
10808 for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
10818 e.exp.destType = destType;
10821 ProcessExpressionType(exp);
10824 curSwitchType = exp.expType;
10827 ProcessStatement(stmt.switchStmt.stmt);
10828 curSwitchType = oldSwitchType;
10833 if(stmt.whileStmt.exp)
10837 FreeType(((Expression)stmt.whileStmt.exp->last).destType);
10838 ((Expression)stmt.whileStmt.exp->last).destType = MkClassType("bool");
10839 ((Expression)stmt.whileStmt.exp->last).destType.truth = true;
10840 for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
10842 ProcessExpressionType(exp);
10845 if(stmt.whileStmt.stmt)
10846 ProcessStatement(stmt.whileStmt.stmt);
10851 if(stmt.doWhile.exp)
10855 if(stmt.doWhile.exp->last)
10857 FreeType(((Expression)stmt.doWhile.exp->last).destType);
10858 ((Expression)stmt.doWhile.exp->last).destType = MkClassType("bool");
10859 ((Expression)stmt.doWhile.exp->last).destType.truth = true;
10861 for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
10863 ProcessExpressionType(exp);
10866 if(stmt.doWhile.stmt)
10867 ProcessStatement(stmt.doWhile.stmt);
10873 if(stmt.forStmt.init)
10874 ProcessStatement(stmt.forStmt.init);
10876 if(stmt.forStmt.check && stmt.forStmt.check.expressions)
10878 FreeType(((Expression)stmt.forStmt.check.expressions->last).destType);
10879 ((Expression)stmt.forStmt.check.expressions->last).destType = MkClassType("bool");
10880 ((Expression)stmt.forStmt.check.expressions->last).destType.truth = true;
10883 if(stmt.forStmt.check)
10884 ProcessStatement(stmt.forStmt.check);
10885 if(stmt.forStmt.increment)
10887 for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
10888 ProcessExpressionType(exp);
10891 if(stmt.forStmt.stmt)
10892 ProcessStatement(stmt.forStmt.stmt);
10897 Identifier id = stmt.forEachStmt.id;
10898 OldList * exp = stmt.forEachStmt.exp;
10899 OldList * filter = stmt.forEachStmt.filter;
10900 Statement block = stmt.forEachStmt.stmt;
10901 char iteratorType[1024];
10904 bool isBuiltin = exp && exp->last &&
10905 (((Expression)exp->last).type == ExpressionType::arrayExp ||
10906 (((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
10907 Expression arrayExp;
10908 char * typeString = null;
10909 int builtinCount = 0;
10911 for(e = exp ? exp->first : null; e; e = e.next)
10915 FreeType(e.destType);
10916 e.destType = ProcessTypeString("Container", false);
10918 if(!isBuiltin || e.next)
10919 ProcessExpressionType(e);
10922 source = (exp && exp->last) ? ((Expression)exp->last).expType : null;
10923 if(isBuiltin || (source && source.kind == classType && source._class && source._class.registered && source._class.registered != containerClass &&
10924 eClass_IsDerived(source._class.registered, containerClass)))
10926 Class _class = source ? source._class.registered : null;
10928 Expression expIt = null;
10929 bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
10930 Class arrayClass = eSystem_FindClass(privateModule, "Array");
10931 Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
10932 Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
10933 stmt.type = compoundStmt;
10935 stmt.compound.context = Context { };
10936 stmt.compound.context.parent = curContext;
10937 curContext = stmt.compound.context;
10939 if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
10941 Class mapClass = eSystem_FindClass(privateModule, "Map");
10942 Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
10943 isCustomAVLTree = true;
10944 if(eClass_IsDerived(source._class.registered, avlTreeClass))
10946 else if(eClass_IsDerived(source._class.registered, mapClass))
10949 else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
10950 else if(source && eClass_IsDerived(source._class.registered, linkListClass))
10952 Class listClass = eSystem_FindClass(privateModule, "List");
10954 isList = eClass_IsDerived(source._class.registered, listClass);
10960 OldList * specs = MkList();
10961 decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
10962 MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
10963 stmt.compound.declarations = MkListOne(
10964 MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
10965 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
10966 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalArray")),
10967 MkInitializerAssignment(MkExpBrackets(exp))))));
10972 char typeStringBuf[1024];
10974 // TODO: Merge this code?
10975 arrayExp = (((Expression)exp->last).type == ExpressionType::arrayExp) ? (Expression)exp->last : ((Expression)exp->last).cast.exp;
10976 if(((Expression)exp->last).type == castExp)
10978 TypeName typeName = ((Expression)exp->last).cast.typeName;
10980 arrayExp.destType = ProcessType(typeName.qualifiers, typeName.declarator);
10983 if(arrayExp.destType && arrayExp.destType.kind == classType && arrayExp.destType._class && arrayExp.destType._class.registered &&
10984 arrayExp.destType._class.registered != containerClass && eClass_IsDerived(arrayExp.destType._class.registered, containerClass) &&
10985 arrayExp.destType._class.registered.templateArgs)
10987 Class templateClass = arrayExp.destType._class.registered;
10988 typeString = templateClass.templateArgs[2].dataTypeString;
10990 else if(arrayExp.list)
10992 // Guess type from expressions in the array
10994 for(e = arrayExp.list->first; e; e = e.next)
10996 ProcessExpressionType(e);
10999 if(!type) { type = e.expType; type.refCount++; }
11002 // if(!MatchType(e.expType, type, null, null, null, false, false, false))
11003 if(!MatchTypeExpression(e, type, null, false))
11009 e = arrayExp.list->first;
11010 ProcessExpressionType(e);
11013 //if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
11014 if(!MatchTypeExpression(e, type, null, false))
11016 FreeType(e.expType);
11027 FreeType(e.expType);
11034 typeStringBuf[0] = '\0';
11035 PrintType(type, typeStringBuf, false, true);
11036 typeString = typeStringBuf;
11042 OldList * initializers = MkList();
11044 OldList * specs = MkList();
11049 builtinCount = arrayExp.list->count;
11050 type = ProcessTypeString(typeString, false);
11051 while(e = arrayExp.list->first)
11053 arrayExp.list->Remove(e);
11056 ProcessExpressionType(e);
11057 ListAdd(initializers, MkInitializerAssignment(e));
11060 delete arrayExp.list;
11062 decl = SpecDeclFromString(typeString, specs, MkDeclaratorIdentifier(id));
11063 stmt.compound.declarations = MkListOne(MkDeclaration(CopyList(specs, CopySpecifier),
11064 MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), /*CopyDeclarator(*/decl/*)*/), null))));
11066 ListAdd(stmt.compound.declarations, MkDeclaration(specs, MkListOne(MkInitDeclarator(MkDeclaratorArray(PlugDeclarator(
11067 /*CopyDeclarator(*/decl/*)*/, MkDeclaratorIdentifier(MkIdentifier("__internalArray"))), null), MkInitializerList(initializers)))));
11069 FreeList(exp, FreeExpression);
11073 arrayExp.expType = ProcessTypeString("Container", false);
11074 Compiler_Error($"Couldn't determine type of array elements\n");
11079 OldList * specs = MkList();
11081 decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs,
11082 MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(id)));
11083 stmt.compound.declarations = MkListOne(
11084 MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11085 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName("BuiltInContainer")),
11086 MkListOne(MkInitDeclarator(MkDeclaratorPointer(MkPointer(null, null), MkDeclaratorIdentifier(MkIdentifier("__internalArray"))),
11087 MkInitializerAssignment(MkExpBrackets(exp))))));
11090 else if(isLinkList && !isList)
11093 OldList * specs = MkList();
11094 decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11095 stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11096 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11097 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalLinkList")),
11098 MkInitializerAssignment(MkExpBrackets(exp))))));
11100 /*else if(isCustomAVLTree)
11103 OldList * specs = MkList();
11104 decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, MkDeclaratorIdentifier(id));
11105 stmt.compound.declarations = MkListOne(MkDeclaration(specs, MkListOne(MkInitDeclarator(decl, null))));
11106 ListAdd(stmt.compound.declarations, MkDeclaration(MkListOne(MkSpecifierName(source._class.registered.fullName)),
11107 MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier("__internalTree")),
11108 MkInitializerAssignment(MkExpBrackets(exp))))));
11110 else if(_class.templateArgs)
11113 sprintf(iteratorType, "MapIterator<%s, %s >", _class.templateArgs[5].dataTypeString, _class.templateArgs[6].dataTypeString);
11115 sprintf(iteratorType, "Iterator<%s, %s >", _class.templateArgs[2].dataTypeString, _class.templateArgs[1].dataTypeString);
11117 stmt.compound.declarations = MkListOne(
11118 MkDeclarationInst(MkInstantiationNamed(MkListOne(MkSpecifierName(iteratorType)),
11119 MkExpIdentifier(id), MkListOne(MkMembersInitList(MkListOne(MkMemberInit(isMap ? MkListOne(MkIdentifier("map")) : null,
11120 MkInitializerAssignment(MkExpBrackets(exp)))))))));
11122 symbol = FindSymbol(id.string, curContext, curContext, false, false);
11124 if(block && block.type == compoundStmt && block.compound.context)
11126 block.compound.context.parent = stmt.compound.context;
11130 block = MkIfStmt(filter, block, null);
11134 stmt.compound.statements = MkListOne(MkForStmt(
11135 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array"))))),
11136 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11137 MkExpOp(MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("array")), '+', MkExpMember(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11138 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11140 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11141 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11142 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11147 //OldList * specs = MkList();
11148 // Declarator decl = SpecDeclFromString(typeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11150 sprintf(count, "%d", builtinCount);
11152 stmt.compound.statements = MkListOne(MkForStmt(
11153 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpIdentifier(MkIdentifier("__internalArray"))))),
11154 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11155 MkExpOp(MkExpIdentifier(MkIdentifier("__internalArray")), '+', MkExpConstant(count))))),
11156 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11160 Declarator decl = SpecDeclFromString(_class.templateArgs[2].dataTypeString, specs, MkDeclaratorPointer(MkPointer(null, null), null));
11161 stmt.compound.statements = MkListOne(MkForStmt(
11162 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))))),
11163 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '<',
11164 MkExpOp(MkExpCast(MkTypeName(specs, decl), MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("data"))), '+', MkExpPointer(MkExpIdentifier(MkIdentifier("__internalArray")), MkIdentifier("count")))))),
11165 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), INC_OP, null)),
11168 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11169 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11170 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11172 else if(isLinkList && !isList)
11174 Class typeClass = eSystem_FindClass(_class.module, _class.templateArgs[3].dataTypeString);
11175 Class listItemClass = eSystem_FindClass(_class.module, "ListItem");
11176 if(typeClass && eClass_IsDerived(typeClass, listItemClass) && _class.templateArgs[5].dataTypeString &&
11177 !strcmp(_class.templateArgs[5].dataTypeString, "LT::link"))
11179 stmt.compound.statements = MkListOne(MkForStmt(
11180 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11181 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11182 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11187 OldList * specs = MkList();
11188 Declarator decl = SpecDeclFromString(_class.templateArgs[3].dataTypeString, specs, null);
11189 stmt.compound.statements = MkListOne(MkForStmt(
11190 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("first"))))),
11191 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11192 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpCast(MkTypeName(specs, decl), MkExpCall(
11193 MkExpMember(MkExpIdentifier(MkIdentifier("__internalLinkList")), MkIdentifier("GetNext")),
11194 MkListOne(MkExpCast(MkTypeName(MkListOne(MkSpecifierName("IteratorPointer")), null), MkExpIdentifier(CopyIdentifier(id)))))))),
11197 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11198 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11199 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11201 /*else if(isCustomAVLTree)
11203 stmt.compound.statements = MkListOne(MkForStmt(
11204 MkExpressionStmt(MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpMember(MkExpIdentifier(
11205 MkIdentifier("__internalTree")), MkIdentifier("root")), MkIdentifier("minimum"))))),
11206 MkExpressionStmt(MkListOne(MkExpIdentifier(CopyIdentifier(id)))),
11207 MkListOne(MkExpOp(MkExpIdentifier(CopyIdentifier(id)), '=', MkExpMember(MkExpIdentifier(CopyIdentifier(id)), MkIdentifier("next")))),
11210 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.init);
11211 ProcessStatement(((Statement)stmt.compound.statements->first).forStmt.check);
11212 ProcessExpressionType(((Statement)stmt.compound.statements->first).forStmt.increment->first);
11216 stmt.compound.statements = MkListOne(MkWhileStmt(MkListOne(MkExpCall(MkExpMember(expIt = MkExpIdentifier(CopyIdentifier(id)),
11217 MkIdentifier("Next")), null)), block));
11219 ProcessExpressionType(expIt);
11220 if(stmt.compound.declarations->first)
11221 ProcessDeclaration(stmt.compound.declarations->first);
11224 symbol.isIterator = isMap ? 2 : ((isArray || isBuiltin) ? 3 : (isLinkList ? (isList ? 5 : 4) : (isCustomAVLTree ? 6 : 1)));
11226 ProcessStatement(stmt);
11227 curContext = stmt.compound.context.parent;
11232 Compiler_Error($"Expression is not a container\n");
11245 if(stmt.expressions)
11247 for(exp = stmt.expressions->first; exp; exp = exp.next)
11251 if(curFunction && !curFunction.type)
11252 curFunction.type = ProcessType(
11253 curFunction.specifiers, curFunction.declarator);
11254 FreeType(exp.destType);
11255 exp.destType = (curFunction && curFunction.type && curFunction.type.kind == functionType) ? curFunction.type.returnType : null;
11256 if(exp.destType) exp.destType.refCount++;
11258 ProcessExpressionType(exp);
11263 case badDeclarationStmt:
11265 ProcessDeclaration(stmt.decl);
11271 if(stmt.asmStmt.inputFields)
11273 for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
11274 if(field.expression)
11275 ProcessExpressionType(field.expression);
11277 if(stmt.asmStmt.outputFields)
11279 for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
11280 if(field.expression)
11281 ProcessExpressionType(field.expression);
11283 if(stmt.asmStmt.clobberedFields)
11285 for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
11287 if(field.expression)
11288 ProcessExpressionType(field.expression);
11295 PropertyWatch propWatch;
11296 OldList * watches = stmt._watch.watches;
11297 Expression object = stmt._watch.object;
11298 Expression watcher = stmt._watch.watcher;
11300 ProcessExpressionType(watcher);
11302 ProcessExpressionType(object);
11306 if(watcher || thisClass)
11308 External external = curExternal;
11309 Context context = curContext;
11311 stmt.type = expressionStmt;
11312 stmt.expressions = MkList();
11314 curExternal = external.prev;
11316 for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11318 ClassFunction func;
11319 char watcherName[1024];
11320 Class watcherClass = watcher ?
11321 ((watcher.expType && watcher.expType.kind == classType && watcher.expType._class) ? watcher.expType._class.registered : null) : thisClass;
11322 External createdExternal;
11324 // Create a declaration above
11325 External externalDecl = MkExternalDeclaration(null);
11326 ast->Insert(curExternal.prev, externalDecl);
11328 sprintf(watcherName,"__ecerePropertyWatcher_%d", propWatcherID++);
11329 if(propWatch.deleteWatch)
11330 strcat(watcherName, "_delete");
11334 for(propID = propWatch.properties->first; propID; propID = propID.next)
11336 strcat(watcherName, "_");
11337 strcat(watcherName, propID.string);
11341 if(object && object.expType && object.expType.kind == classType && object.expType._class && object.expType._class.registered)
11343 // TESTING THIS STUFF... BEWARE OF SYMBOL ID ISSUES
11344 func = MkClassFunction(MkListOne(MkSpecifier(VOID)), null, MkDeclaratorFunction(MkDeclaratorIdentifier(MkIdentifier(watcherName)),
11345 //MkListOne(MkTypeName(MkListOne(MkSpecifier(VOID)), null))), null);
11346 MkListOne(MkTypeName(MkListOne(MkSpecifierName(object.expType._class.string)), MkDeclaratorIdentifier(MkIdentifier("value"))))), null);
11347 ProcessClassFunctionBody(func, propWatch.compound);
11348 propWatch.compound = null;
11350 //afterExternal = afterExternal ? afterExternal : curExternal;
11352 //createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal.prev);
11353 createdExternal = ProcessClassFunction(watcherClass, func, ast, curExternal, true);
11355 createdExternal.symbol.idCode = external.symbol.idCode;
11357 curExternal = createdExternal;
11358 ProcessFunction(createdExternal.function);
11361 // Create a declaration above
11363 Declaration decl = MkDeclaration(CopyList(createdExternal.function.specifiers, CopySpecifier),
11364 MkListOne(MkInitDeclarator(CopyDeclarator(createdExternal.function.declarator), null)));
11365 externalDecl.declaration = decl;
11366 if(decl.symbol && !decl.symbol.pointerExternal)
11367 decl.symbol.pointerExternal = externalDecl;
11370 if(propWatch.deleteWatch)
11372 OldList * args = MkList();
11373 ListAdd(args, CopyExpression(object));
11374 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11375 ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11376 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_WatchDestruction")), args));
11380 Class _class = object.expType._class.registered;
11383 for(propID = propWatch.properties->first; propID; propID = propID.next)
11385 char propName[1024];
11386 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11389 char getName[1024], setName[1024];
11390 OldList * args = MkList();
11392 DeclareProperty(prop, setName, getName);
11394 // eInstance_Watch(stmt.watch.object, prop, stmt.watch.watcher, callback);
11395 strcpy(propName, "__ecereProp_");
11396 FullClassNameCat(propName, prop._class.fullName, false);
11397 strcat(propName, "_");
11398 // strcat(propName, prop.name);
11399 FullClassNameCat(propName, prop.name, true);
11401 ListAdd(args, CopyExpression(object));
11402 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11403 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11404 ListAdd(args, MkExpIdentifier(MkIdentifier(watcherName)));
11406 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
11409 Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11414 Compiler_Error($"Invalid watched object\n");
11417 curExternal = external;
11418 curContext = context;
11421 FreeExpression(watcher);
11423 FreeExpression(object);
11424 FreeList(watches, FreePropertyWatch);
11427 Compiler_Error($"No observer specified and not inside a _class\n");
11431 for(propWatch = watches->first; propWatch; propWatch = propWatch.next)
11433 ProcessStatement(propWatch.compound);
11439 case fireWatchersStmt:
11441 OldList * watches = stmt._watch.watches;
11442 Expression object = stmt._watch.object;
11444 // DEBUGGER BUG: Why doesn't watches evaluate to null??
11445 // printf("%X\n", watches);
11446 // printf("%X\n", stmt._watch.watches);
11448 ProcessExpressionType(object);
11453 ((object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null) : thisClass;
11459 stmt.type = expressionStmt;
11460 stmt.expressions = MkList();
11462 // Check if we're inside a property set
11463 if(!watches && curFunction.propSet && (!object || (object.type == identifierExp && !strcmp(object.identifier.string, "this"))))
11465 watches = MkListOne(MkIdentifier(curFunction.propSet.string));
11469 //Compiler_Error($"No property specified and not inside a property set\n");
11473 for(propID = watches->first; propID; propID = propID.next)
11475 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11478 CreateFireWatcher(prop, object, stmt);
11481 Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
11486 // Fire all properties!
11489 for(base = _class; base; base = base.base)
11491 for(prop = base.membersAndProperties.first; prop; prop = prop.next)
11493 if(prop.isProperty && prop.isWatchable)
11495 CreateFireWatcher(prop, object, stmt);
11502 FreeExpression(object);
11503 FreeList(watches, FreeIdentifier);
11506 Compiler_Error($"Invalid object specified and not inside a class\n");
11510 case stopWatchingStmt:
11512 OldList * watches = stmt._watch.watches;
11513 Expression object = stmt._watch.object;
11514 Expression watcher = stmt._watch.watcher;
11517 ProcessExpressionType(object);
11519 ProcessExpressionType(watcher);
11522 _class = (object && object.expType && object.expType.kind == classType && object.expType._class) ? object.expType._class.registered : null;
11524 if(watcher || thisClass)
11530 stmt.type = expressionStmt;
11531 stmt.expressions = MkList();
11536 // eInstance_StopWatching(object, null, watcher);
11538 ListAdd(args, CopyExpression(object));
11539 ListAdd(args, MkExpConstant("0"));
11540 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11541 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11545 for(propID = watches->first; propID; propID = propID.next)
11547 char propName[1024];
11548 Property prop = eClass_FindProperty(_class, propID.string, privateModule);
11551 char getName[1024], setName[1024];
11552 OldList * args = MkList();
11554 DeclareProperty(prop, setName, getName);
11556 // eInstance_StopWatching(object, prop, watcher);
11557 strcpy(propName, "__ecereProp_");
11558 FullClassNameCat(propName, prop._class.fullName, false);
11559 strcat(propName, "_");
11560 // strcat(propName, prop.name);
11561 FullClassNameCat(propName, prop.name, true);
11562 MangleClassName(propName);
11564 ListAdd(args, CopyExpression(object));
11565 ListAdd(args, MkExpIdentifier(MkIdentifier(propName)));
11566 ListAdd(args, watcher ? CopyExpression(watcher) : MkExpIdentifier(MkIdentifier("this")));
11567 ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
11570 Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
11575 FreeExpression(object);
11577 FreeExpression(watcher);
11578 FreeList(watches, FreeIdentifier);
11581 Compiler_Error($"Invalid object specified and not inside a class\n");
11584 Compiler_Error($"No observer specified and not inside a class\n");
11591 static void ProcessFunction(FunctionDefinition function)
11593 Identifier id = GetDeclId(function.declarator);
11594 Symbol symbol = function.declarator ? function.declarator.symbol : null;
11595 Type type = symbol ? symbol.type : null;
11596 Class oldThisClass = thisClass;
11597 Context oldTopContext = topContext;
11599 yylloc = function.loc;
11600 // Process thisClass
11602 if(type && type.thisClass)
11604 Symbol classSym = type.thisClass;
11605 Class _class = type.thisClass.registered;
11606 char className[1024];
11607 char structName[1024];
11608 Declarator funcDecl;
11611 bool typedObject = false;
11613 if(_class && !_class.base)
11615 _class = currentClass;
11616 if(_class && !_class.symbol)
11617 _class.symbol = FindClass(_class.fullName);
11618 classSym = _class ? _class.symbol : null;
11619 typedObject = true;
11622 thisClass = _class;
11624 if(inCompiler && _class)
11626 if(type.kind == functionType)
11628 if(symbol.type.params.count == 1 && ((Type)symbol.type.params.first).kind == voidType)
11630 //TypeName param = symbol.type.params.first;
11631 Type param = symbol.type.params.first;
11632 symbol.type.params.Remove(param);
11633 //FreeTypeName(param);
11636 if(type.classObjectType != classPointer)
11638 symbol.type.params.Insert(null, MkClassType(_class.fullName));
11639 symbol.type.staticMethod = true;
11640 symbol.type.thisClass = null;
11642 // HIGH DANGER: VERIFYING THIS...
11643 symbol.type.extraParam = false;
11647 strcpy(className, "__ecereClass_");
11648 FullClassNameCat(className, _class.fullName, true);
11650 MangleClassName(className);
11653 FullClassNameCat(structName, _class.fullName, false);
11658 funcDecl = GetFuncDecl(function.declarator);
11661 if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11663 TypeName param = funcDecl.function.parameters->first;
11664 if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11666 funcDecl.function.parameters->Remove(param);
11667 FreeTypeName(param);
11671 // DANGER: Watch for this... Check if it's a Conversion?
11672 // if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11674 // WAS TRYING THIS FOR CONVERSION PROPERTIES ON NOHEAD CLASSES: if((_class.type == structClass) || function != (FunctionDefinition)symbol.externalSet)
11675 if(!function.propertyNoThis)
11677 TypeName thisParam;
11679 if(type.classObjectType != classPointer)
11681 thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11682 if(!funcDecl.function.parameters)
11683 funcDecl.function.parameters = MkList();
11684 funcDecl.function.parameters->Insert(null, thisParam);
11689 if(type.classObjectType != classPointer)
11691 if(type.byReference || _class.type == unitClass || _class.type == systemClass || _class.type == enumClass || _class.type == bitClass)
11692 thisParam.declarator = MkDeclaratorPointer(MkPointer(null,null), thisParam.declarator);
11695 thisParam = TypeName
11697 declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
11698 qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
11700 funcDecl.function.parameters->Insert(null, thisParam);
11705 if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11707 InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11708 funcDecl = GetFuncDecl(initDecl.declarator);
11711 if(funcDecl.function.parameters && funcDecl.function.parameters->count == 1)
11713 TypeName param = funcDecl.function.parameters->first;
11714 if(param.qualifiers && param.qualifiers->count == 1 && ((Specifier)param.qualifiers->first).specifier == VOID && !param.declarator)
11716 funcDecl.function.parameters->Remove(param);
11717 FreeTypeName(param);
11721 if(type.classObjectType != classPointer)
11723 // DANGER: Watch for this... Check if it's a Conversion?
11724 if((_class.type != bitClass && _class.type != unitClass && _class.type != enumClass) || function != (FunctionDefinition)symbol.externalSet)
11726 TypeName thisParam = QMkClass(_class.fullName, MkDeclaratorIdentifier(MkIdentifier("this")));
11728 if(!funcDecl.function.parameters)
11729 funcDecl.function.parameters = MkList();
11730 funcDecl.function.parameters->Insert(null, thisParam);
11737 // Add this to the context
11740 if(type.classObjectType != classPointer)
11742 thisSymbol = Symbol
11744 string = CopyString("this");
11745 type = classSym ? MkClassType(classSym.string) : null; //_class.fullName);
11747 function.body.compound.context.symbols.Add((BTNode)thisSymbol);
11749 if(typedObject && thisSymbol.type)
11751 thisSymbol.type.classObjectType = ClassObjectType::typedObject;
11752 thisSymbol.type.byReference = type.byReference;
11754 thisSymbol = Symbol { string = CopyString("class") };
11755 function.body.compound.context.symbols.Add(thisSymbol);
11761 // Pointer to class data
11763 if(inCompiler && _class && (_class.type == normalClass /*|| _class.type == noHeadClass*/) && type.classObjectType != classPointer)
11765 DataMember member = null;
11768 for(base = _class; base && base.type != systemClass; base = base.next)
11770 for(member = base.membersAndProperties.first; member; member = member.next)
11771 if(!member.isProperty)
11777 for(member = _class.membersAndProperties.first; member; member = member.next)
11778 if(!member.isProperty)
11782 char pointerName[1024];
11785 Initializer initializer;
11786 Expression exp, bytePtr;
11788 strcpy(pointerName, "__ecerePointer_");
11789 FullClassNameCat(pointerName, _class.fullName, false);
11791 char className[1024];
11792 strcpy(className, "__ecereClass_");
11793 FullClassNameCat(className, classSym.string, true);
11794 MangleClassName(className);
11797 DeclareClass(classSym, className);
11801 bytePtr = QBrackets(MkExpCast(QMkType("char", QMkPtrDecl(null)), QMkExpId("this")));
11806 sprintf(string, "%d", _class.offset);
11807 exp = QBrackets(MkExpOp(bytePtr, '+', MkExpConstant(string)));
11811 // ([bytePtr] + [className]->offset)
11812 exp = QBrackets(MkExpOp(bytePtr, '+',
11813 MkExpPointer(QMkExpId(className), MkIdentifier("offset"))));
11816 // (this ? [exp] : 0)
11817 exp = QBrackets(QMkExpCond(QMkExpId("this"), exp, MkExpConstant("0")));
11821 kind = pointerType;
11822 type = Type { refCount = 1, kind = voidType };
11827 yylloc = function.body.loc;
11828 // ([structName] *) [exp]
11829 // initializer = MkInitializerAssignment(MkExpCast(QMkType(structName, QMkPtrDecl(null)), exp));
11830 initializer = MkInitializerAssignment(
11831 MkExpCast(MkTypeName(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)), MkDeclaratorPointer(MkPointer(null, null), null)), exp));
11833 // [structName] * [pointerName] = [initializer];
11834 // decl = QMkDeclaration(structName, MkInitDeclarator(QMkPtrDecl(pointerName), initializer));
11837 Context prevContext = curContext;
11838 curContext = function.body.compound.context;
11840 decl = MkDeclaration(MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier(structName), null)),
11841 MkListOne(MkInitDeclarator(QMkPtrDecl(pointerName), initializer)));
11843 curContext = prevContext;
11847 decl.symbol = null;
11849 if(!function.body.compound.declarations)
11850 function.body.compound.declarations = MkList();
11851 function.body.compound.declarations->Insert(null, decl);
11857 // Loop through the function and replace undeclared identifiers
11858 // which are a member of the class (methods, properties or data)
11859 // by "this.[member]"
11866 FreeSpecifier(id._class);
11869 if(symbol && symbol.pointerExternal && symbol.pointerExternal.type == declarationExternal)
11871 InitDeclarator initDecl = symbol.pointerExternal.declaration.declarators->first;
11872 id = GetDeclId(initDecl.declarator);
11874 FreeSpecifier(id._class);
11879 topContext = function.body.compound.context;
11881 FunctionDefinition oldFunction = curFunction;
11882 curFunction = function;
11884 ProcessStatement(function.body);
11886 // If this is a property set and no firewatchers has been done yet, add one here
11887 if(inCompiler && function.propSet && !function.propSet.fireWatchersDone)
11889 Statement prevCompound = curCompound;
11890 Context prevContext = curContext;
11892 Statement fireWatchers = MkFireWatchersStmt(null, null);
11893 if(!function.body.compound.statements) function.body.compound.statements = MkList();
11894 ListAdd(function.body.compound.statements, fireWatchers);
11896 curCompound = function.body;
11897 curContext = function.body.compound.context;
11899 ProcessStatement(fireWatchers);
11901 curContext = prevContext;
11902 curCompound = prevCompound;
11906 curFunction = oldFunction;
11909 if(function.declarator)
11911 ProcessDeclarator(function.declarator);
11914 topContext = oldTopContext;
11915 thisClass = oldThisClass;
11918 /////////// INSTANTIATIONS / DATA TYPES PASS /////////////////////////////////////////////
11919 static void ProcessClass(OldList definitions, Symbol symbol)
11922 External external = curExternal;
11923 Class regClass = symbol ? symbol.registered : null;
11925 // Process all functions
11926 for(def = definitions.first; def; def = def.next)
11928 if(def.type == functionClassDef)
11930 if(def.function.declarator)
11931 curExternal = def.function.declarator.symbol.pointerExternal;
11933 curExternal = external;
11935 ProcessFunction((FunctionDefinition)def.function);
11937 else if(def.type == declarationClassDef)
11939 if(def.decl.type == instDeclaration)
11941 thisClass = regClass;
11942 ProcessInstantiationType(def.decl.inst);
11948 Class backThisClass = thisClass;
11949 if(regClass) thisClass = regClass;
11950 ProcessDeclaration(def.decl);
11951 thisClass = backThisClass;
11954 else if(def.type == defaultPropertiesClassDef && def.defProperties)
11956 MemberInit defProperty;
11958 // Add this to the context
11959 Symbol thisSymbol = Symbol
11961 string = CopyString("this");
11962 type = regClass ? MkClassType(regClass.fullName) : null;
11964 globalContext.symbols.Add((BTNode)thisSymbol);
11966 for(defProperty = def.defProperties->first; defProperty; defProperty = defProperty.next)
11968 thisClass = regClass;
11969 ProcessMemberInitData(defProperty, regClass, null, null, null, null);
11973 globalContext.symbols.Remove((BTNode)thisSymbol);
11974 FreeSymbol(thisSymbol);
11976 else if(def.type == propertyClassDef && def.propertyDef)
11978 PropertyDef prop = def.propertyDef;
11980 // Add this to the context
11982 Symbol thisSymbol = Symbol { string = CopyString("this"), type = MkClassType(regClass.fullName) };
11983 globalContext.symbols.Add(thisSymbol);
11986 thisClass = regClass;
11993 string = CopyString("this");
11994 type = MkClassType(regClass.fullName);
11996 prop.setStmt.compound.context.symbols.Add((BTNode)thisSymbol);
11999 curExternal = prop.symbol ? prop.symbol.externalSet : null;
12000 ProcessStatement(prop.setStmt);
12008 string = CopyString("this");
12009 type = MkClassType(regClass.fullName);
12011 prop.getStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12014 curExternal = prop.symbol ? prop.symbol.externalGet : null;
12015 ProcessStatement(prop.getStmt);
12023 string = CopyString("this");
12024 type = MkClassType(regClass.fullName);
12026 prop.issetStmt.compound.context.symbols.Add((BTNode)thisSymbol);
12029 curExternal = prop.symbol ? prop.symbol.externalIsSet : null;
12030 ProcessStatement(prop.issetStmt);
12036 globalContext.symbols.Remove(thisSymbol);
12037 FreeSymbol(thisSymbol);
12040 else if(def.type == propertyWatchClassDef && def.propertyWatch)
12042 PropertyWatch propertyWatch = def.propertyWatch;
12044 thisClass = regClass;
12045 if(propertyWatch.compound)
12049 string = CopyString("this");
12050 type = regClass ? MkClassType(regClass.fullName) : null;
12053 propertyWatch.compound.compound.context.symbols.Add((BTNode)thisSymbol);
12055 curExternal = null;
12056 ProcessStatement(propertyWatch.compound);
12063 void DeclareFunctionUtil(String s)
12065 GlobalFunction function = eSystem_FindFunction(privateModule, s);
12070 if(function.module.importType != staticImport && (!function.dataType || !function.dataType.dllExport))
12071 strcpy(name, "__ecereFunction_");
12072 FullClassNameCat(name, s, false); // Why is this using FullClassNameCat ?
12073 DeclareFunction(function, name);
12077 void ComputeDataTypes()
12081 currentClass = null;
12083 containerClass = eSystem_FindClass(GetPrivateModule(), "Container");
12085 temp.symbol = Symbol { id = -1000, idCode = -1000 };
12087 // WHERE SHOULD THIS GO?
12088 // curExternal = ast->first;
12089 ast->Insert(null, temp);
12091 curExternal = temp;
12093 DeclareFunctionUtil("eSystem_New");
12094 DeclareFunctionUtil("eSystem_New0");
12095 DeclareFunctionUtil("eSystem_Renew");
12096 DeclareFunctionUtil("eSystem_Renew0");
12097 DeclareFunctionUtil("eClass_GetProperty");
12099 DeclareStruct("ecere::com::Class", false);
12100 DeclareStruct("ecere::com::Instance", false);
12101 DeclareStruct("ecere::com::Property", false);
12102 DeclareStruct("ecere::com::DataMember", false);
12103 DeclareStruct("ecere::com::Method", false);
12104 DeclareStruct("ecere::com::SerialBuffer", false);
12105 DeclareStruct("ecere::com::ClassTemplateArgument", false);
12109 for(external = ast->first; external; external = external.next)
12111 afterExternal = curExternal = external;
12112 if(external.type == functionExternal)
12114 currentClass = external.function._class;
12115 ProcessFunction(external.function);
12117 // There shouldn't be any _class member access here anyways...
12118 else if(external.type == declarationExternal)
12120 currentClass = null;
12121 ProcessDeclaration(external.declaration);
12123 else if(external.type == classExternal)
12125 ClassDefinition _class = external._class;
12126 currentClass = external.symbol.registered;
12127 if(_class.definitions)
12129 ProcessClass(_class.definitions, _class.symbol);
12133 // Free class data...
12134 ast->Remove(external);
12138 else if(external.type == nameSpaceExternal)
12140 thisNameSpace = external.id.string;
12143 currentClass = null;
12144 thisNameSpace = null;
12146 delete temp.symbol;