{
TempFile f { };
int count;
+ bool backOutputLineNumbers = outputLineNumbers;
+ outputLineNumbers = false;
if(exp)
OutputExpression(exp, f);
count += f.Read(string + count, 1, 1023);
string[count] = '\0';
delete f;
+
+ outputLineNumbers = backOutputLineNumbers;
}
}
case classType:
return type1._class != type2._class;
case pointerType:
- return NeedCast(type1.type, type2.type);
+ return (type1.type && type2.type && type1.type.constant != type2.type.constant) || NeedCast(type1.type, type2.type);
default:
return true; //false; ????
}
public char * PrintInt(int64 result)
{
char temp[100];
- if(result > MAXINT64)
- sprintf(temp, FORMAT64HEXLL /*"0x%I64XLL"*/, result);
+ if(result > MAXINT)
+ sprintf(temp, FORMAT64HEX /*"0x%I64XLL"*/, result);
else
- sprintf(temp, FORMAT64DLL /*"%I64d"*/, result);
+ sprintf(temp, FORMAT64D /*"%I64d"*/, result);
+ if(result > MAXINT || result < MININT)
+ strcat(temp, "LL");
return CopyString(temp);
}
{
char temp[100];
if(result > MAXDWORD)
- sprintf(temp, FORMAT64HEXLL /*"0x%I64xLL"*/, result);
+ sprintf(temp, FORMAT64HEX /*"0x%I64xLL"*/, result);
else
sprintf(temp, FORMAT64HEX /*"0x%I64x"*/, result);
+ if(result > MAXDWORD)
+ strcat(temp, "LL");
return CopyString(temp);
}
public char * PrintFloat(float result)
{
char temp[350];
- sprintf(temp, "%.16ff", result);
+ if(result.isInf)
+ {
+ if(result.signBit)
+ strcpy(temp, "-inf");
+ else
+ strcpy(temp, "inf");
+ }
+ else if(result.isNan)
+ {
+ if(result.signBit)
+ strcpy(temp, "-nan");
+ else
+ strcpy(temp, "nan");
+ }
+ else
+ sprintf(temp, "%.16ff", result);
return CopyString(temp);
}
public char * PrintDouble(double result)
{
char temp[350];
- sprintf(temp, "%.16f", result);
+ if(result.isInf)
+ {
+ if(result.signBit)
+ strcpy(temp, "-inf");
+ else
+ strcpy(temp, "inf");
+ }
+ else if(result.isNan)
+ {
+ if(result.signBit)
+ strcpy(temp, "-nan");
+ else
+ strcpy(temp, "nan");
+ }
+ else
+ sprintf(temp, "%.16f", result);
return CopyString(temp);
}
//public Operand GetOperand(Expression exp);
#define GETVALUE(name, t) \
- public bool Get##name(Expression exp, t * value2) \
+ public bool GetOp##name(Operand op2, t * value2) \
{ \
- Operand op2 = GetOperand(exp); \
if(op2.kind == intType && op2.type.isSigned) *value2 = (t) op2.i; \
else if(op2.kind == intType) *value2 = (t) op2.ui; \
else if(op2.kind == int64Type && op2.type.isSigned) *value2 = (t) op2.i64; \
else \
return false; \
return true; \
+ } \
+ public bool Get##name(Expression exp, t * value2) \
+ { \
+ Operand op2 = GetOperand(exp); \
+ return GetOp##name(op2, value2); \
}
// To help the deubugger currently not preprocessing...
if(member || ((_class.type == bitClass || _class.type == normalClass || _class.type == structClass || _class.type == noHeadClass) &&
(_class.type == bitClass || (!_class.structSize || _class.structSize == _class.offset)) && _class.computeSize))
{
- int c;
int unionMemberOffset = 0;
int bitFields = 0;
{
ProcessExpressionType(type.arraySizeExp);
ComputeExpression(type.arraySizeExp);
- if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType && type.arraySizeExp.expType.kind != enumType &&
+ if(!type.arraySizeExp.isConstant || (type.arraySizeExp.expType.kind != intType &&
+ type.arraySizeExp.expType.kind != shortType &&
+ type.arraySizeExp.expType.kind != charType &&
+ type.arraySizeExp.expType.kind != longType &&
+ type.arraySizeExp.expType.kind != int64Type &&
+ type.arraySizeExp.expType.kind != intSizeType &&
+ type.arraySizeExp.expType.kind != intPtrType &&
+ type.arraySizeExp.expType.kind != enumType &&
(type.arraySizeExp.expType.kind != classType || !type.arraySizeExp.expType._class.registered || type.arraySizeExp.expType._class.registered.type != enumClass)))
{
Location oldLoc = yylloc;
DataMember topMember = isMember ? (DataMember) _class : null;
uint totalSize = 0;
uint maxSize = 0;
- int alignment, size;
+ int alignment;
+ uint size;
DataMember member;
Context context = isMember ? null : SetupTemplatesContext(_class);
if(addedPadding)
static int DeclareMembers(Class _class, bool isMember)
{
DataMember topMember = isMember ? (DataMember) _class : null;
- uint totalSize = 0;
DataMember member;
Context context = isMember ? null : SetupTemplatesContext(_class);
return topMember ? topMember.memberID : _class.memberID;
}
-void DeclareStruct(char * name, bool skipNoHead)
+void DeclareStruct(const char * name, bool skipNoHead)
{
External external = null;
Symbol classSym = FindClass(name);
OldList * specifiers, * declarators;
OldList * declarations = null;
char structName[1024];
+ Specifier spec = null;
external = (classSym.registered && classSym.registered.type == structClass) ?
classSym.pointerExternal : classSym.structExternal;
structName[0] = 0;
FullClassNameCat(structName, name, false);
+ if(external && external.declaration && external.declaration.specifiers)
+ {
+ for(spec = external.declaration.specifiers->first; spec; spec = spec.next)
+ {
+ if(spec.type == structSpecifier || spec.type == unionSpecifier)
+ break;
+ }
+ }
+
/*if(!external)
external = MkExternalDeclaration(null);*/
- if(!skipNoHead)
+ if(!skipNoHead && (!spec || !spec.definitions))
{
bool addedPadding = false;
classSym.declaredStructSym = true;
}
if(skipNoHead || declarations)
{
- if(external && external.declaration)
+ if(spec)
{
- ((Specifier)external.declaration.specifiers->first).definitions = declarations;
+ if(declarations)
+ spec.definitions = declarations;
if(curExternal && curExternal.symbol && curExternal.symbol.idCode < classSym.id)
{
classSym._import.properties.Add(symbol._import);
}
imported = true;
- if(prop._class.module != privateModule && prop._class.module.importType != staticImport)
+ // Ugly work around for isNan properties declared within float/double classes which are initialized with ecereCOM
+ if((prop._class.module != privateModule || !strcmp(prop._class.name, "float") || !strcmp(prop._class.name, "double")) &&
+ prop._class.module.importType != staticImport)
dllImport = true;
}
ClassTemplateArgument arg = _class.templateArgs[id];
if(arg.dataTypeString)
{
+ bool constant = type.constant;
// FreeType(type);
type = ProcessTypeString(arg.dataTypeString, false);
+ if(type.kind == classType && constant) type.constant = true;
+ else if(type.kind == pointerType)
+ {
+ Type t = type.type;
+ while(t.kind == pointerType) t = t.type;
+ if(constant) t.constant = constant;
+ }
freeType = true;
if(type && _class.templateClass)
type.passAsTemplate = true;
Expression exp;
char * string = PrintHexUInt64(arg.expression.ui64);
exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+ delete string;
ProcessExpressionType(exp);
ComputeExpression(exp);
}
}
//else if(!MatchTypes(member.exp.expType, type, null, _class, null, true, true, false, false))
- else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false))
+ else if(!MatchTypes(member.initializer.exp.expType, type, null, null, _class, true, true, false, false, true))
{
Compiler_Error($"incompatible instance method %s\n", ident.string);
}
if(inCompiler)
{
-
- Type type = declarator.symbol.type;
+ //Type type = declarator.symbol.type;
External oldExternal = curExternal;
// *** Commented this out... Any negative impact? Yes: makes double prototypes declarations... Why was it commented out?
}
}
-public void DeclareMethod(Method method, char * name)
+public void DeclareMethod(Method method, const char * name)
{
Symbol symbol = method.symbol;
if(!symbol || (!symbol.pointerExternal && method.type == virtualMethod) || symbol.id > (curExternal ? curExternal.symbol.idCode : -1))
if(!method.dataType.dllExport)
{
imported = true;
- if(method._class.module != privateModule && method._class.module.importType != staticImport)
+ if((method._class.module != privateModule || !strcmp(method._class.name, "float") || !strcmp(method._class.name, "double")) && method._class.module.importType != staticImport)
dllImport = true;
}
}
Type resultType;
};
-public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams, bool isConversionExploration)
+public bool MatchTypes(Type source, Type dest, OldList conversions, Class owningClassSource, Class owningClassDest, bool doConversion, bool enumBaseType, bool acceptReversedParams,
+ bool isConversionExploration, bool warnConst)
{
if(source && dest)
{
+ if(warnConst &&
+ ((source.kind == classType && source._class && source._class.registered) || source.kind == arrayType || source.kind == pointerType) &&
+ ((dest.kind == classType && dest._class && dest._class.registered) || /*dest.kind == arrayType || */dest.kind == pointerType))
+ {
+ Class sourceClass = source.kind == classType ? source._class.registered : null;
+ Class destClass = dest.kind == classType ? dest._class.registered : null;
+ if((!sourceClass || (sourceClass && sourceClass.type == normalClass && !sourceClass.structSize)) &&
+ (!destClass || (destClass && destClass.type == normalClass && !destClass.structSize)))
+ {
+ Type sourceType = source, destType = dest;
+ while(sourceType.type && (sourceType.kind == pointerType || sourceType.kind == arrayType)) sourceType = sourceType.type;
+ while(destType.type && (destType.kind == pointerType || destType.kind == arrayType)) destType = destType.type;
+ if(!destType.constant && sourceType.constant)
+ Compiler_Warning($"discarding const qualifier\n");
+ }
+ }
// Property convert;
if(source.kind == templateType && dest.kind != templateType)
if(!isConversionExploration && source.kind == pointerType && source.type.kind == voidType &&
((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))
|| dest.kind == subClassType || dest.kind == pointerType || dest.kind == arrayType || dest.kind == functionType || dest.kind == thisClassType)
-
/* dest.kind != voidType && dest.kind != structType && dest.kind != unionType */
/*&& (dest.kind != classType || dest._class.registered.type != structClass)*/)
if(!convert.dataType)
convert.dataType = ProcessTypeString(convert.dataTypeString, false);
- if(MatchTypes(convert.dataType, dest, conversions, null, null, false, true, false, true))
+ // Only go ahead with this conversion flow while processing an existing conversion if the conversion data type is a class
+ if((!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+ MatchTypes(convert.dataType, dest, conversions, null, null,
+ (convert.dataType.kind == classType && !strcmp(convert.dataTypeString, "String")) ? true : false,
+ convert.dataType.kind == classType, false, true, warnConst))
{
if(!conversions && !convert.Get)
return true;
Conversion conv { convert = convert, isGet = true };
// conversions.Add(conv);
conversions.Insert(after, conv);
+
return true;
}
}
{
if(convert.memberAccess == publicAccess || _class.module == privateModule)
{
+ Type constType = null;
+ bool success = false;
// Conversion after = (conversions != null) ? conversions.last : null;
if(!convert.dataType)
convert.dataType = ProcessTypeString(convert.dataTypeString, false);
+
+ if(warnConst && convert.dataType.kind == pointerType && convert.dataType.type && dest.constant)
+ {
+ Type ptrType { };
+ constType = { kind = pointerType, refCount = 1, type = ptrType };
+ CopyTypeInto(ptrType, convert.dataType.type);
+ ptrType.refCount++;
+ ptrType.constant = true;
+ }
+
// Just added this equality check to prevent recursion.... Make it safer?
// Changed enumBaseType to false here to prevent all int-compatible enums to show up in AnchorValues
- if(convert.dataType != dest && MatchTypes(source, convert.dataType, conversions, null, null, true, false /*true*/, false, true))
+ if((constType || convert.dataType != dest) && MatchTypes(source, constType ? constType : convert.dataType, conversions, null, null, true, false /*true*/, false, true, warnConst))
{
if(!conversions && !convert.Set)
- return true;
+ success = true;
else if(conversions != null)
{
if(_class.type == unitClass && convert.dataType.kind == classType && convert.dataType._class &&
convert.dataType._class.registered && _class.base == convert.dataType._class.registered.base &&
(source.kind != classType || source._class.registered != _class.base))
- return true;
+ success = true;
else
{
// *** Testing this! ***
Conversion conv { convert = convert };
conversions.Add(conv);
//conversions.Insert(after, conv);
- return true;
+ success = true;
}
}
}
+ if(success)
+ return true;
+ if(constType)
+ FreeType(constType);
}
}
}
if(dest._class.registered.dataType.kind == classType || source.truth || dest.truth/* ||
!strcmp(dest._class.registered.name, "bool") || (source.kind == classType && !strcmp(source._class.string, "bool"))*/)
{
- if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+ if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, dest._class.registered.dataType.kind == classType, false, false, warnConst))
{
return true;
}
if(!convert.dataType)
convert.dataType = ProcessTypeString(convert.dataTypeString, false);
- if(convert.dataType != source && MatchTypes(convert.dataType, dest, conversions, null, null, true, true, false, true))
+ if(convert.dataType != source &&
+ (!isConversionExploration || convert.dataType.kind == classType || !strcmp(_class.name, "String")) &&
+ MatchTypes(convert.dataType, dest, conversions, null, null, convert.dataType.kind == classType, convert.dataType.kind == classType, false, true, warnConst))
{
if(!conversions && !convert.Get)
return true;
{
if(!source._class.registered.dataType)
source._class.registered.dataType = ProcessTypeString(source._class.registered.dataTypeString, false);
- if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, true, true, false, false))
+ if(!isConversionExploration || source._class.registered.dataType.kind == classType || !strcmp(source._class.registered.name, "String"))
{
- return true;
+ if(MatchTypes(source._class.registered.dataType, dest, conversions, null, null, source._class.registered.dataType.kind == classType, source._class.registered.dataType.kind == classType, false, false, warnConst))
+ return true;
+ // For bool to be accepted by byte, short, etc.
+ else if(MatchTypes(dest, source._class.registered.dataType, null, null, null, false, false, false, false, warnConst))
+ return true;
}
}
}
else if(source.kind == enumType &&
(dest.kind == intType || dest.kind == shortType || dest.kind == charType || source.kind == _BoolType || dest.kind == longType || dest.kind == int64Type || dest.kind == intPtrType || dest.kind == intSizeType))
return true;
- else if(dest.kind == enumType &&
+ else if(dest.kind == enumType && !isConversionExploration &&
(source.kind == intType || source.kind == shortType || source.kind == charType || source.kind == _BoolType || source.kind == longType || source.kind == int64Type || source.kind == intPtrType || source.kind == intSizeType))
return true;
else if((dest.kind == functionType || (dest.kind == pointerType && dest.type.kind == functionType) || dest.kind == methodType) &&
// Source return type must be derived from destination return type
- if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false))
+ if(!MatchTypes(source.returnType, dest.returnType, null, null, null, true, true, false, false, warnConst))
{
Compiler_Warning($"incompatible return type for function\n");
return false;
}
// paramDest must be derived from paramSource
- if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false) &&
- (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false)))
+ if(!MatchTypes(paramDestType, paramSourceType, null, null, null, true, true, false, false, warnConst) &&
+ (!acceptReversedParams || !MatchTypes(paramSourceType, paramDestType, null, null, null, true, true, false, false, warnConst)))
{
char type[1024];
type[0] = 0;
else if((dest.kind == pointerType || dest.kind == arrayType) &&
(source.kind == arrayType || source.kind == pointerType))
{
- if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false))
+ if(MatchTypes(source.type, dest.type, null, null, null, true, true, false, false, warnConst))
return true;
}
}
_class.symbol = FindClass(_class.fullName);
type._class = _class.symbol;
- if(MatchTypes(type, dest, &converts, null, null, true, false, false, false))
+ if(MatchTypes(type, dest, &converts, null, null, true, false, false, false, false))
{
NamedLink value;
Class enumClass = eSystem_FindClass(privateModule, "enum");
return false;
}
-bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla)
+bool MatchTypeExpression(Expression sourceExp, Type dest, OldList conversions, bool skipUnitBla, bool warnConst)
{
- Type source = sourceExp.expType;
+ Type source;
Type realDest = dest;
Type backupSourceExpType = null;
+ Expression computedExp = sourceExp;
+ dest.refCount++;
+
+ if(sourceExp.isConstant && sourceExp.type != constantExp && sourceExp.type != identifierExp && sourceExp.type != castExp &&
+ dest.kind == classType && dest._class && dest._class.registered && dest._class.registered.type == enumClass)
+ {
+ computedExp = CopyExpression(sourceExp); // Keep the original expression, but compute for checking enum ranges
+ ComputeExpression(computedExp /*sourceExp*/);
+ }
+
+ source = sourceExp.expType;
if(dest.kind == pointerType && sourceExp.type == constantExp && !strtoul(sourceExp.constant, null, 0))
+ {
+ if(computedExp != sourceExp)
+ {
+ FreeExpression(computedExp);
+ computedExp = sourceExp;
+ }
+ FreeType(dest);
return true;
+ }
if(!skipUnitBla && source && dest && source.kind == classType && dest.kind == classType)
{
destBase = destBase.base);
//if(source._class.registered == dest._class.registered)
if(sourceBase == destBase)
- return true;
- }
+ {
+ if(computedExp != sourceExp)
+ {
+ FreeExpression(computedExp);
+ computedExp = sourceExp;
+ }
+ FreeType(dest);
+ return true;
+ }
+ }
}
if(source)
int64 value = MAXINT;
source.refCount++;
- dest.refCount++;
- if(sourceExp.type == constantExp)
+ if(computedExp.type == constantExp)
{
if(source.isSigned)
- value = strtoll(sourceExp.constant, null, 0);
+ value = strtoll(computedExp.constant, null, 0);
else
- value = strtoull(sourceExp.constant, null, 0);
+ value = strtoull(computedExp.constant, null, 0);
}
- else if(sourceExp.type == opExp && sourceExp.op.op == '-' && !sourceExp.op.exp1 && sourceExp.op.exp2 && sourceExp.op.exp2.type == constantExp)
+ else if(computedExp.type == opExp && sourceExp.op.op == '-' && !computedExp.op.exp1 && computedExp.op.exp2 && computedExp.op.exp2.type == constantExp)
{
if(source.isSigned)
- value = -strtoll(sourceExp.op.exp2.constant, null, 0);
+ value = -strtoll(computedExp.op.exp2.constant, null, 0);
else
- value = -strtoull(sourceExp.op.exp2.constant, null, 0);
+ value = -strtoull(computedExp.op.exp2.constant, null, 0);
+ }
+ if(computedExp != sourceExp)
+ {
+ FreeExpression(computedExp);
+ computedExp = sourceExp;
}
if(dest.kind != classType && source.kind == classType && source._class && source._class.registered &&
tempType._class = _class.symbol;
tempType.truth = dest.truth;
if(tempType._class)
- MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
+ MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
// NOTE: To handle bad warnings on int64 vs 32 bit eda::Id incompatibilities
backupSourceExpType = sourceExp.expType;
{
if(!dest._class.registered.dataType)
dest._class.registered.dataType = ProcessTypeString(dest._class.registered.dataTypeString, false);
- if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false))
+ if(MatchTypes(source, dest._class.registered.dataType, conversions, null, null, true, true, false, false, warnConst))
{
FreeType(source);
FreeType(sourceExp.expType);
{
Class _class = source._class ? source._class.registered : null;
- if(_class && (_class.type == unitClass || !strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass )) // TOCHECK: enumClass, bitClass is new here...
+ if(_class && (_class.type == unitClass || /*!strcmp(_class.fullName, "bool") || /*_class.type == enumClass || */_class.type == bitClass )) // TOCHECK: enumClass, bitClass is new here...
{
/*
if(dest.kind != classType)
tempType.classObjectType = source.classObjectType;
if(tempType._class)
- MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false);
+ MatchTypes(tempSource, tempDest, conversions, null, null, true, true, false, false, warnConst);
// PUT THIS BACK TESTING UNITS?
if(conversions.last)
if(!flag)
{
- if(MatchTypes(source, dest, conversions, null, null, true, true, false, false))
+ if(MatchTypes(source, dest, conversions, null, null, true, true, false, false, warnConst))
{
FreeType(source);
FreeType(dest);
if(dest.kind == classType)
{
Class _class = dest._class ? dest._class.registered : null;
- if(_class && !dest.truth && (_class.type == unitClass || !strcmp(_class.fullName, "bool") ||
+ bool fittingValue = false;
+ if(_class && _class.type == enumClass)
+ {
+ Class enumClass = eSystem_FindClass(privateModule, "enum");
+ EnumClassData c = ACCESS_CLASSDATA(_class, enumClass);
+ if(c && value >= 0 && value <= c.largest)
+ fittingValue = true;
+ }
+
+ if(_class && !dest.truth && (_class.type == unitClass || fittingValue ||
(/*_class.type == enumClass*/_class.type != structClass && !value && source.kind == intType) || _class.type == bitClass)) // TOCHECK: enumClass, bitClass is new here...
{
if(_class.type == normalClass || _class.type == noHeadClass)
return false;
}
- if(!flag)
+ if(!flag && !sourceExp.opDestType)
{
Expression newExp { };
*newExp = *sourceExp;
}
else
{
+ if(computedExp != sourceExp)
+ {
+ FreeExpression(computedExp);
+ computedExp = sourceExp;
+ }
+
while((sourceExp.type == bracketsExp || sourceExp.type == extensionExpressionExp) && sourceExp.list) sourceExp = sourceExp.list->last;
if(sourceExp.type == identifierExp)
{
sourceExp.constant = CopyString(constant);
//for(;_class.base && _class.base.type != systemClass; _class = _class.base);
}
+ FreeType(dest);
return true;
}
}
// Loop through all enum classes
if(dest.classObjectType != typedObject && dest.kind == classType /*!= ellipsisType */&& MatchWithEnums_Module(privateModule, sourceExp, dest, id.string, conversions))
+ {
+ FreeType(dest);
return true;
+ }
}
+ FreeType(dest);
}
return false;
}
{ \
t value2 = op2.m; \
exp.type = constantExp; \
- exp.string = p(op1.m o value2); \
+ exp.string = p((t)(op1.m o value2)); \
if(!exp.expType) \
{ exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
return true; \
}
-#define BINARY_DIVIDE(o, name, m, t, p) \
+#define BINARY_DIVIDEINT(o, name, m, t, p) \
static bool name(Expression exp, Operand op1, Operand op2) \
{ \
t value2 = op2.m; \
return true; \
}
+#define BINARY_DIVIDEREAL(o, name, m, t, p) \
+ static bool name(Expression exp, Operand op1, Operand op2) \
+ { \
+ t value2 = op2.m; \
+ exp.type = constantExp; \
+ exp.string = p(op1.m o value2); \
+ if(!exp.expType) \
+ { exp.expType = op1.type; if(op1.type) op1.type.refCount++; } \
+ return true; \
+ }
+
#define UNARY(o, name, m, t, p) \
static bool name(Expression exp, Operand op1) \
{ \
#define OPERATOR_ALL(macro, o, name) \
macro(o, Int##name, i, int, PrintInt) \
macro(o, UInt##name, ui, unsigned int, PrintUInt) \
- macro(o, Int64##name, i, int, PrintInt64) \
- macro(o, UInt64##name, ui, unsigned int, PrintUInt64) \
+ macro(o, Int64##name, i64, int64, PrintInt64) \
+ macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
macro(o, Short##name, s, short, PrintShort) \
macro(o, UShort##name, us, unsigned short, PrintUShort) \
macro(o, Char##name, c, char, PrintChar) \
#define OPERATOR_INTTYPES(macro, o, name) \
macro(o, Int##name, i, int, PrintInt) \
macro(o, UInt##name, ui, unsigned int, PrintUInt) \
- macro(o, Int64##name, i, int, PrintInt64) \
- macro(o, UInt64##name, ui, unsigned int, PrintUInt64) \
+ macro(o, Int64##name, i64, int64, PrintInt64) \
+ macro(o, UInt64##name, ui64, uint64, PrintUInt64) \
macro(o, Short##name, s, short, PrintShort) \
macro(o, UShort##name, us, unsigned short, PrintUShort) \
macro(o, Char##name, c, char, PrintChar) \
macro(o, UChar##name, uc, unsigned char, PrintUChar)
+#define OPERATOR_REALTYPES(macro, o, name) \
+ macro(o, Float##name, f, float, PrintFloat) \
+ macro(o, Double##name, d, double, PrintDouble)
// binary arithmetic
OPERATOR_ALL(BINARY, +, Add)
OPERATOR_ALL(BINARY, -, Sub)
OPERATOR_ALL(BINARY, *, Mul)
-OPERATOR_ALL(BINARY_DIVIDE, /, Div)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %, Mod)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /, Div)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /, Div)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %, Mod)
// unary arithmetic
OPERATOR_ALL(UNARY, -, Neg)
OPERATOR_ALL(BINARY, +=, AddAsign)
OPERATOR_ALL(BINARY, -=, SubAsign)
OPERATOR_ALL(BINARY, *=, MulAsign)
-OPERATOR_ALL(BINARY_DIVIDE, /=, DivAsign)
-OPERATOR_INTTYPES(BINARY_DIVIDE, %=, ModAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, /=, DivAsign)
+OPERATOR_REALTYPES(BINARY_DIVIDEREAL, /=, DivAsign)
+OPERATOR_INTTYPES(BINARY_DIVIDEINT, %=, ModAsign)
// binary bitwise
OPERATOR_INTTYPES(BINARY, &, BitAnd)
OPERATOR_ALL(BINARY, <=, SmaEqu)
// tertiary condition operator
-OPERATOR_ALL(TERTIARY, ?, Cond)
+OPERATOR_INTTYPES(TERTIARY, ?, Cond)
//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
#define OPERATOR_TABLE_ALL(name, type) \
case 'v': output[d] = '\v'; break;
case '\\': output[d] = '\\'; break;
case '\"': output[d] = '\"'; break;
- default: output[d++] = '\\'; output[d] = ch;
- //default: output[d] = ch;
+ case '\'': output[d] = '\''; break;
+ default: output[d] = ch;
}
d++;
escaped = false;
output[d] = '\0';
}
+// String Unescape Copy
+
+// TOFIX: THIS DOESN'T HANDLE NUMERIC ESCAPE CODES (OCTAL/HEXADECIMAL...)?
+// This is the same as ReadString above (which also misses numeric escape codes) except it doesn't handle external quotes
+public int UnescapeString(char * d, char * s, int len)
+{
+ int j = 0, k = 0;
+ char ch;
+ while(j < len && (ch = s[j]))
+ {
+ switch(ch)
+ {
+ case '\\':
+ switch((ch = s[++j]))
+ {
+ case 'n': d[k] = '\n'; break;
+ case 't': d[k] = '\t'; break;
+ case 'a': d[k] = '\a'; break;
+ case 'b': d[k] = '\b'; break;
+ case 'f': d[k] = '\f'; break;
+ case 'r': d[k] = '\r'; break;
+ case 'v': d[k] = '\v'; break;
+ case '\\': d[k] = '\\'; break;
+ case '\"': d[k] = '\"'; break;
+ case '\'': d[k] = '\''; break;
+ default: d[k] = '\\'; d[k] = ch;
+ }
+ break;
+ default:
+ d[k] = ch;
+ }
+ j++, k++;
+ }
+ d[k] = '\0';
+ return k;
+}
+
+public char * OffsetEscapedString(char * s, int len, int offset)
+{
+ char ch;
+ int j = 0, k = 0;
+ while(j < len && k < offset && (ch = s[j]))
+ {
+ if(ch == '\\') ++j;
+ j++, k++;
+ }
+ return (k == offset) ? s + j : null;
+}
+
public Operand GetOperand(Expression exp)
{
Operand op { };
type = type._class.registered.dataType;
}
- op.kind = type.kind;
- op.type = exp.expType;
- if(exp.isConstant && exp.type == constantExp)
+ if(exp.type == stringExp && op.kind == pointerType)
{
+ op.ui64 = (uint64)exp.string;
+ op.kind = pointerType;
+ op.ops = uint64Ops;
+ }
+ else if(exp.isConstant && exp.type == constantExp)
+ {
+ op.kind = type.kind;
+ op.type = exp.expType;
+
switch(op.kind)
{
case _BoolType:
case charType:
{
if(exp.constant[0] == '\'')
+ {
op.c = exp.constant[1];
+ op.ops = charOps;
+ }
else if(type.isSigned)
{
op.c = (char)strtol(exp.constant, null, 0);
if(type.isSigned)
{
op.i64 = (int64)_strtoi64(exp.constant, null, 0);
- op.ops = intOps;
+ op.ops = int64Ops;
}
else
{
op.ui64 = (uint64)_strtoui64(exp.constant, null, 0);
- op.ops = uintOps;
+ op.ops = uint64Ops;
}
op.kind = int64Type;
break;
op.kind = int64Type;
break;
case floatType:
- op.f = (float)strtod(exp.constant, null);
+ if(!strcmp(exp.constant, "inf")) op.f = float::inf();
+ else if(!strcmp(exp.constant, "-inf")) op.f = -float::inf();
+ else if(!strcmp(exp.constant, "nan")) op.f = float::nan();
+ else if(!strcmp(exp.constant, "-nan")) op.f = -float::nan();
+ else
+ op.f = (float)strtod(exp.constant, null);
op.ops = floatOps;
break;
case doubleType:
- op.d = (double)strtod(exp.constant, null);
+ if(!strcmp(exp.constant, "inf")) op.d = double::inf();
+ else if(!strcmp(exp.constant, "-inf")) op.d = -double::inf();
+ else if(!strcmp(exp.constant, "nan")) op.d = double::nan();
+ else if(!strcmp(exp.constant, "-nan")) op.d = -double::nan();
+ else
+ op.d = (double)strtod(exp.constant, null);
op.ops = doubleOps;
break;
//case classType: For when we have operator overloading...
case classType:
op.ui64 = _strtoui64(exp.constant, null, 0);
op.kind = pointerType;
- op.ops = uintOps;
+ op.ops = uint64Ops;
// op.ptrSize =
break;
}
return op;
}
-static void UnusedFunction()
+static __attribute__((unused)) void UnusedFunction()
{
int a;
a.OnGetString(0,0,0);
{
BitMember bitMember = (BitMember) dataMember;
Type type;
- int part = 0;
- GetInt(value, &part);
+ uint64 part;
bits = (bits & ~bitMember.mask);
if(!bitMember.dataType)
bitMember.dataType = ProcessTypeString(bitMember.dataTypeString, false);
-
type = bitMember.dataType;
-
if(type.kind == classType && type._class && type._class.registered)
{
if(!type._class.registered.dataType)
type._class.registered.dataType = ProcessTypeString(type._class.registered.dataTypeString, false);
type = type._class.registered.dataType;
}
-
switch(type.kind)
{
case _BoolType:
- case charType:
- if(type.isSigned)
- bits |= ((char)part << bitMember.pos);
- else
- bits |= ((unsigned char)part << bitMember.pos);
- break;
- case shortType:
- if(type.isSigned)
- bits |= ((short)part << bitMember.pos);
- else
- bits |= ((unsigned short)part << bitMember.pos);
- break;
+ case charType: { byte v; type.isSigned ? GetChar(value, (char *)&v) : GetUChar(value, &v); part = (uint64)v; break; }
+ case shortType: { uint16 v; type.isSigned ? GetShort(value, (uint16 *)&v) : GetUShort(value, &v); part = (uint64)v; break; }
case intType:
- case longType:
- if(type.isSigned)
- bits |= ((int)part << bitMember.pos);
- else
- bits |= ((unsigned int)part << bitMember.pos);
- break;
- case int64Type:
- if(type.isSigned)
- bits |= ((int64)part << bitMember.pos);
- else
- bits |= ((uint64)part << bitMember.pos);
- break;
- case intPtrType:
- if(type.isSigned)
- {
- bits |= ((intptr)part << bitMember.pos);
- }
- else
- {
- bits |= ((uintptr)part << bitMember.pos);
- }
- break;
- case intSizeType:
- if(type.isSigned)
- {
- bits |= ((ssize_t)(intsize)part << bitMember.pos);
- }
- else
- {
- bits |= ((size_t) (uintsize)part << bitMember.pos);
- }
- break;
+ case longType: { uint v; type.isSigned ? GetInt(value, (uint *)&v) : GetUInt(value, &v); part = (uint64)v; break; }
+ case int64Type: { uint64 v; type.isSigned ? GetInt64(value, (uint64 *)&v) : GetUInt64(value, &v); part = (uint64)v; break; }
+ case intPtrType: { uintptr v; type.isSigned ? GetIntPtr(value, (uintptr *)&v) : GetUIntPtr(value, &v); part = (uint64)v; break; }
+ case intSizeType: { uintsize v; type.isSigned ? GetIntSize(value, (uintsize *)&v) : GetUIntSize(value, &v); part = (uint64)v; break; }
}
+ bits |= part << bitMember.pos;
}
}
}
}
}
+static bool Promote(Operand op, TypeKind kind, bool isSigned)
+{
+ bool result = false;
+ switch(kind)
+ {
+ case shortType:
+ if(op.kind == charType || op.kind == enumType || op.kind == _BoolType)
+ result = isSigned ? GetOpShort(op, &op.s) : GetOpUShort(op, &op.us);
+ break;
+ case intType:
+ case longType:
+ if(op.kind == charType || op.kind == shortType || op.kind == enumType || op.kind == _BoolType)
+ result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+ break;
+ case int64Type:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+ op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+ result = isSigned ? GetOpInt64(op, &op.i64) : GetOpUInt64(op, &op.ui64);
+ break;
+ case floatType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType ||
+ op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+ result = GetOpFloat(op, &op.f);
+ break;
+ case doubleType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType ||
+ op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+ result = GetOpDouble(op, &op.d);
+ break;
+ case pointerType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+ op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+ result = GetOpUIntPtr(op, &op.ui64);
+ break;
+ case enumType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == int64Type || op.kind == longType || op.kind == floatType || op.kind == doubleType ||
+ op.kind == pointerType || op.kind == enumType || op.kind == intPtrType || op.kind == intSizeType || op.kind == _BoolType)
+ result = isSigned ? GetOpInt(op, &op.i) : GetOpUInt(op, &op.ui);
+ break;
+ case intPtrType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+ result = isSigned ? GetOpIntPtr(op, &op.i64) : GetOpUIntPtr(op, &op.i64);
+ break;
+ case intSizeType:
+ if(op.kind == charType || op.kind == shortType || op.kind == intType || op.kind == longType || op.kind == enumType || op.kind == _BoolType)
+ result = isSigned ? GetOpIntSize(op, &op.ui64) : GetOpUIntSize(op, &op.ui64);
+ break;
+ }
+ return result;
+}
+
void CallOperator(Expression exp, Expression exp1, Expression exp2, Operand op1, Operand op2)
{
if(exp.op.op == SIZEOF)
}
else
{
+ if(op1 && op2 && op1.type && op2.type && op1.kind != op2.kind)
+ {
+ if(Promote(op2, op1.kind, op1.type.isSigned))
+ op2.kind = op1.kind, op2.ops = op1.ops;
+ else if(Promote(op1, op2.kind, op2.type.isSigned))
+ op1.kind = op2.kind, op1.ops = op2.ops;
+ }
switch(exp.op.op)
{
// binary arithmetic
// We don't care about operations with only exp2 (INC_OP, DEC_OP...)
if(exp.op.exp2)
- ComputeExpression(exp.op.exp2);
+ {
+ Expression e = exp.op.exp2;
+
+ while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+ {
+ if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+ {
+ if(e.type == extensionCompoundExp)
+ e = ((Statement)e.compound.compound.statements->last).expressions->last;
+ else
+ e = e.list->last;
+ }
+ }
+ if(exp.op.op == TokenType::sizeOf && e && e.expType)
+ {
+ if(e.type == stringExp && e.string)
+ {
+ char * string = e.string;
+ int len = strlen(string);
+ char * tmp = new char[len-2+1];
+ len = UnescapeString(tmp, string + 1, len - 2);
+ delete tmp;
+ FreeExpContents(exp);
+ exp.type = constantExp;
+ exp.constant = PrintUInt(len + 1);
+ }
+ else
+ {
+ Type type = e.expType;
+ type.refCount++;
+ FreeExpContents(exp);
+ exp.type = constantExp;
+ exp.constant = PrintUInt(ComputeTypeSize(type));
+ FreeType(type);
+ }
+ break;
+ }
+ else
+ ComputeExpression(exp.op.exp2);
+ }
if(exp.op.exp1)
{
ComputeExpression(exp.op.exp1);
if(!n)
{
OldList * list = exp.list;
+ Expression prev = exp.prev;
+ Expression next = exp.next;
ComputeExpression(e);
//FreeExpContents(exp);
FreeType(exp.expType);
FreeType(exp.destType);
*exp = *e;
+ exp.prev = prev;
+ exp.next = next;
delete e;
delete list;
}
void (*Set)(void *, void *) = (void *)prop.Set;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
exp.type = instanceExp;
Set(exp.instance.data, value.instance.data);
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
exp.type = instanceExp;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
exp.type = instanceExp;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
exp.type = instanceExp;
PopulateInstance(exp.instance);
break;
}
+ case floatType:
+ {
+ float floatValue;
+ void (*Set)(void *, float) = (void *)prop.Set;
+
+ exp.instance = Instantiation { };
+ exp.instance.data = new0 byte[_class.structSize];
+ exp.instance._class = MkSpecifierName(_class.fullName);
+ exp.instance.loc = exp.loc;
+ exp.type = instanceExp;
+
+ GetFloat(value, &floatValue);
+
+ Set(exp.instance.data, floatValue);
+ PopulateInstance(exp.instance);
+ break;
+ }
case doubleType:
{
double doubleValue;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
exp.type = instanceExp;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
//exp.instance.fullSet = true;
exp.type = instanceExp;
exp.instance = Instantiation { };
exp.instance.data = new0 byte[_class.structSize];
- exp.instance._class = MkSpecifierName/*MkClassName*/(_class.fullName);
+ exp.instance._class = MkSpecifierName(_class.fullName);
exp.instance.loc = exp.loc;
//exp.instance.fullSet = true;
exp.type = instanceExp;
case charType:
if(type.isSigned)
{
- char value;
- GetChar(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintChar(value);
- exp.type = constantExp;
+ char value = 0;
+ if(GetChar(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintChar(value);
+ exp.type = constantExp;
+ }
}
else
{
- unsigned char value;
- GetUChar(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUChar(value);
- exp.type = constantExp;
+ unsigned char value = 0;
+ if(GetUChar(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUChar(value);
+ exp.type = constantExp;
+ }
}
break;
case shortType:
if(type.isSigned)
{
- short value;
- GetShort(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintShort(value);
- exp.type = constantExp;
+ short value = 0;
+ if(GetShort(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintShort(value);
+ exp.type = constantExp;
+ }
}
else
{
- unsigned short value;
- GetUShort(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUShort(value);
- exp.type = constantExp;
+ unsigned short value = 0;
+ if(GetUShort(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUShort(value);
+ exp.type = constantExp;
+ }
}
break;
case intType:
if(type.isSigned)
{
- int value;
- GetInt(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintInt(value);
- exp.type = constantExp;
+ int value = 0;
+ if(GetInt(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintInt(value);
+ exp.type = constantExp;
+ }
}
else
{
- unsigned int value;
- GetUInt(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUInt(value);
- exp.type = constantExp;
+ unsigned int value = 0;
+ if(GetUInt(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUInt(value);
+ exp.type = constantExp;
+ }
}
break;
case int64Type:
if(type.isSigned)
{
- int64 value;
- GetInt64(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintInt64(value);
- exp.type = constantExp;
+ int64 value = 0;
+ if(GetInt64(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintInt64(value);
+ exp.type = constantExp;
+ }
}
else
{
- uint64 value;
- GetUInt64(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUInt64(value);
- exp.type = constantExp;
+ uint64 value = 0;
+ if(GetUInt64(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUInt64(value);
+ exp.type = constantExp;
+ }
}
break;
case intPtrType:
if(type.isSigned)
{
- intptr value;
- GetIntPtr(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintInt64((int64)value);
- exp.type = constantExp;
+ intptr value = 0;
+ if(GetIntPtr(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintInt64((int64)value);
+ exp.type = constantExp;
+ }
}
else
{
- uintptr value;
- GetUIntPtr(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUInt64((uint64)value);
- exp.type = constantExp;
+ uintptr value = 0;
+ if(GetUIntPtr(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUInt64((uint64)value);
+ exp.type = constantExp;
+ }
}
break;
case intSizeType:
if(type.isSigned)
{
- intsize value;
- GetIntSize(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintInt64((int64)value);
- exp.type = constantExp;
+ intsize value = 0;
+ if(GetIntSize(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintInt64((int64)value);
+ exp.type = constantExp;
+ }
}
else
{
- uintsize value;
- GetUIntSize(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintUInt64((uint64)value);
- exp.type = constantExp;
+ uintsize value = 0;
+ if(GetUIntSize(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintUInt64((uint64)value);
+ exp.type = constantExp;
+ }
}
break;
case floatType:
{
- float value;
- GetFloat(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintFloat(value);
- exp.type = constantExp;
+ float value = 0;
+ if(GetFloat(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintFloat(value);
+ exp.type = constantExp;
+ }
break;
}
case doubleType:
{
- double value;
- GetDouble(e, &value);
- FreeExpContents(exp);
- exp.constant = PrintDouble(value);
- exp.type = constantExp;
+ double value = 0;
+ if(GetDouble(e, &value))
+ {
+ FreeExpContents(exp);
+ exp.constant = PrintDouble(value);
+ exp.type = constantExp;
+ }
break;
}
}
}
}
-static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla)
+static bool CheckExpressionType(Expression exp, Type destType, bool skipUnitBla, bool warnConst)
{
bool result = true;
if(destType)
if(destType.kind == voidType)
return false;
- if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla))
+ if(!MatchTypeExpression(exp, destType, &converts, skipUnitBla, warnConst))
result = false;
if(converts.count)
{
// TODO: Check this...
*newExp = *exp;
+ newExp.prev = null;
+ newExp.next = null;
newExp.destType = null;
if(convert.isGet)
if(!result && exp.expType && converts.count) // TO TEST: Added converts.count here to avoid a double warning with function type
{
- result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false);
+ result = MatchTypes(exp.expType, exp.destType, null, null, null, true, true, false, false, warnConst);
}
if(!result && exp.expType && exp.destType)
{
if(exp.destType && exp.destType.passAsTemplate && exp.expType && exp.expType.kind != templateType && !exp.expType.passAsTemplate)
{
Expression newExp { };
- Statement compound;
Context context;
*newExp = *exp;
if(exp.destType) exp.destType.refCount++;
// - Tree of all symbols within (stored without namespace)
// - Tree of sub-namespaces
-static Symbol ScanWithNameSpace(BinaryTree tree, char * nameSpace, char * name)
+static Symbol ScanWithNameSpace(BinaryTree tree, const char * nameSpace, const char * name)
{
int nsLen = strlen(nameSpace);
Symbol symbol;
return null;
}
-static Symbol FindWithNameSpace(BinaryTree tree, char * name)
+static Symbol FindWithNameSpace(BinaryTree tree, const char * name)
{
int c;
char nameSpace[1024];
- char * namePart;
+ const char * namePart;
bool gotColon = false;
nameSpace[0] = '\0';
static void ProcessDeclaration(Declaration decl);
-/*static */Symbol FindSymbol(char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
+/*static */Symbol FindSymbol(const char * name, Context startContext, Context endContext, bool isStruct, bool globalNameSpace)
{
#ifdef _DEBUG
//Time startTime = GetTime();
return null;
}
+public bool GetParseError() { return parseError; }
+
Expression ParseExpressionString(char * expression)
{
+ parseError = false;
+
fileInput = TempFile { };
fileInput.Write(expression, 1, strlen(expression));
fileInput.Seek(0, start);
}
else if(!e.byReference || (_class && _class.type == noHeadClass)) // TESTING THIS HERE...
{
- Expression checkedExp, newExp;
+ Expression checkedExp; //, newExp;
{
// TODO: Move code from debugTools.ec for hasAddress flag, this is just temporary
}
}
+void ApplyLocation(Expression exp, Location loc)
+{
+ exp.loc = loc;
+ switch(exp.type)
+ {
+ case opExp:
+ if(exp.op.exp1) ApplyLocation(exp.op.exp1, loc);
+ if(exp.op.exp2) ApplyLocation(exp.op.exp2, loc);
+ break;
+ case bracketsExp:
+ if(exp.list)
+ {
+ Expression e;
+ for(e = exp.list->first; e; e = e.next)
+ ApplyLocation(e, loc);
+ }
+ break;
+ case indexExp:
+ if(exp.index.index)
+ {
+ Expression e;
+ for(e = exp.index.index->first; e; e = e.next)
+ ApplyLocation(e, loc);
+ }
+ if(exp.index.exp)
+ ApplyLocation(exp.index.exp, loc);
+ break;
+ case callExp:
+ if(exp.call.arguments)
+ {
+ Expression arg;
+ for(arg = exp.call.arguments->first; arg; arg = arg.next)
+ ApplyLocation(arg, loc);
+ }
+ if(exp.call.exp)
+ ApplyLocation(exp.call.exp, loc);
+ break;
+ case memberExp:
+ case pointerExp:
+ if(exp.member.exp)
+ ApplyLocation(exp.member.exp, loc);
+ break;
+ case castExp:
+ if(exp.cast.exp)
+ ApplyLocation(exp.cast.exp, loc);
+ break;
+ case conditionExp:
+ if(exp.cond.exp)
+ {
+ Expression e;
+ for(e = exp.cond.exp->first; e; e = e.next)
+ ApplyLocation(e, loc);
+ }
+ if(exp.cond.cond)
+ ApplyLocation(exp.cond.cond, loc);
+ if(exp.cond.elseExp)
+ ApplyLocation(exp.cond.elseExp, loc);
+ break;
+ case vaArgExp:
+ if(exp.vaArg.exp)
+ ApplyLocation(exp.vaArg.exp, loc);
+ break;
+ default:
+ break;
+ }
+}
+
void ProcessExpressionType(Expression exp)
{
bool unresolved = false;
case identifierExp:
{
Identifier id = exp.identifier;
- if(!id) return;
+ if(!id || !topContext) return;
// DOING THIS LATER NOW...
if(id._class && id._class.name)
// Enums should be resolved here (Special pass in opExp to fix identifiers not seen as enum on the first pass)
if(!symbol/* && exp.destType*/)
{
- if(exp.destType && CheckExpressionType(exp, exp.destType, false))
+ if(exp.destType && CheckExpressionType(exp, exp.destType, false, false))
break;
else
{
exp.expType = type;
if(type)
type.refCount++;
- if(type && (type.kind == enumType || (_class && _class.type == enumClass)))
+
+ // Commented this out, it was making non-constant enum parameters seen as constant
+ // enums should have been resolved by ResolveIdWithClass, changed to constantExp and marked as constant
+ if(type && (type.kind == enumType /*|| (_class && _class.type == enumClass)*/))
// Add missing cases here... enum Classes...
exp.isConstant = true;
if(c == definedExpStackPos && c < sizeof(definedExpStack) / sizeof(void *))
{
Location backupYylloc = yylloc;
+ File backInput = fileInput;
definedExpStack[definedExpStackPos++] = definedExp;
+
fileInput = TempFile { };
fileInput.Write(definedExp.value, 1, strlen(definedExp.value));
fileInput.Seek(0, start);
resetScanner();
expression_yyparse();
delete fileInput;
+ if(backInput)
+ fileInput = backInput;
yylloc = backupYylloc;
FreeIdentifier(id);
exp.type = bracketsExp;
exp.list = MkListOne(parsedExpression);
- parsedExpression.loc = yylloc;
+ ApplyLocation(parsedExpression, yylloc);
ProcessExpressionType(exp);
definedExpStackPos--;
return;
//_class = classSym ? classSym.registered : null;
ProcessInstantiationType(exp.instance);
+
exp.isConstant = exp.instance.isConstant;
/*
else
{
bool isSigned = constant[0] == '-';
- int64 i64 = strtoll(constant, null, 0);
- uint64 ui64 = strtoull(constant, null, 0);
- bool is64Bit = false;
+ char * endP = null;
+ int64 i64 = strtoll(constant, &endP, 0);
+ uint64 ui64 = strtoull(constant, &endP, 0);
+ bool is64Bit = endP && (!strcmp(endP, "LL") || !strcmp(endP, "ll"));
if(isSigned)
{
if(i64 < MININT)
bool useDestType = false, useSideType = false;
Location oldyylloc = yylloc;
bool useSideUnit = false;
+ Class destClass = (exp.destType && exp.destType.kind == classType && exp.destType._class) ? exp.destType._class.registered : null;
// Dummy type to prevent ProcessExpression of operands to say unresolved identifiers yet
Type dummy
case '+':
case '-':
useSideUnit = true;
+ useSideType = true;
+ useDestType = true;
+ break;
+
+ case LEFT_OP:
+ case RIGHT_OP:
+ useSideType = true;
+ useDestType = true;
+ break;
- // Just added these... testing
case '|':
- case '&':
case '^':
+ useSideType = true;
+ useDestType = true;
+ break;
- // DANGER: Verify units
case '/':
case '%':
+ useSideType = true;
+ useDestType = true;
+ break;
+ case '&':
case '*':
-
- if(exp.op.op != '*' || exp.op.exp1)
+ if(exp.op.exp1)
{
+ // For & operator, useDestType nicely ensures the result will fit in a bool (TODO: Fix for generic enum)
useSideType = true;
useDestType = true;
}
}
//dummy.kind = TypeDummy;
-
if(exp.op.exp1)
{
- if(exp.destType && exp.destType.kind == classType &&
- exp.destType._class && exp.destType._class.registered && useDestType &&
+ // Added this check here to use the dest type only for units derived from the base unit
+ // So that untyped units will use the side unit as opposed to the untyped destination unit
+ // This fixes (#771) sin(Degrees { 5 } + 5) to be equivalent to sin(Degrees { 10 }), since sin expects a generic Angle
+ if(exp.op.exp2 && useSideUnit && useDestType && destClass && destClass.type == unitClass && destClass.base.type != unitClass)
+ useDestType = false;
- ((exp.destType._class.registered.type == unitClass && useSideUnit) ||
- exp.destType._class.registered.type == enumClass ||
- exp.destType._class.registered.type == bitClass
- ))
+ if(destClass && useDestType &&
+ ((destClass.type == unitClass && useSideUnit) || destClass.type == enumClass || destClass.type == bitClass))
//(exp.destType._class.registered.type == unitClass || exp.destType._class.registered.type == enumClass) && useDestType)
{
if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
exp.op.exp1.destType = exp.destType;
+ exp.op.exp1.opDestType = true;
if(exp.destType)
exp.destType.refCount++;
}
// TESTING THIS HERE...
if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count++;
- ProcessExpressionType(exp.op.exp1);
+ ProcessExpressionType(exp.op.exp1);
if(exp.op.exp1.destType && exp.op.op != '=') exp.op.exp1.destType.count--;
+ exp.op.exp1.opDestType = false;
+
+ // Fix for unit and ++ / --
+ if(!exp.op.exp2 && (exp.op.op == INC_OP || exp.op.op == DEC_OP) && exp.op.exp1.expType && exp.op.exp1.expType.kind == classType &&
+ exp.op.exp1.expType._class && exp.op.exp1.expType._class.registered && exp.op.exp1.expType._class.registered.type == unitClass)
+ {
+ exp.op.exp2 = MkExpConstant("1");
+ exp.op.op = exp.op.op == INC_OP ? ADD_ASSIGN : SUB_ASSIGN;
+ assign = true;
+ }
+
if(exp.op.exp1.destType == dummy)
{
FreeType(dummy);
else
{
exp.op.exp2.destType = exp.destType;
+ if(!exp.op.exp1 || exp.op.op != '&')
+ exp.op.exp2.opDestType = true;
if(exp.destType)
exp.destType.refCount++;
}
if(type1) type1.refCount++;
exp.expType = type1;
}
- else if(exp.destType && exp.destType.kind == classType &&
- exp.destType._class && exp.destType._class.registered &&
-
- ((exp.destType._class.registered.type == unitClass && useDestType && useSideUnit) ||
- (exp.destType._class.registered.type == enumClass && useDestType))
- )
+ else if(destClass &&
+ ((destClass.type == unitClass && useDestType && useSideUnit) ||
+ (destClass.type == enumClass && useDestType)))
{
if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
exp.op.exp2.destType = exp.destType;
+ if(exp.op.op != '&')
+ exp.op.exp2.opDestType = true;
if(exp.destType)
exp.destType.refCount++;
}
type1.refCount++;
}
if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count++;
+ // Cannot lose the cast on a sizeof
+ if(exp.op.op == SIZEOF)
+ {
+ Expression e = exp.op.exp2;
+ while((e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp) && e.list)
+ {
+ if(e.type == bracketsExp || e.type == extensionExpressionExp || e.type == extensionCompoundExp)
+ {
+ if(e.type == extensionCompoundExp)
+ e = ((Statement)e.compound.compound.statements->last).expressions->last;
+ else
+ e = e.list->last;
+ }
+ }
+ if(e.type == castExp && e.cast.exp)
+ e.cast.exp.needCast = true;
+ }
ProcessExpressionType(exp.op.exp2);
+ exp.op.exp2.opDestType = false;
if(exp.op.exp2.destType && exp.op.op != '=') exp.op.exp2.destType.count--;
if(assign && type1 && type1.kind == pointerType && exp.op.exp2.expType)
type2.isSigned = true;
}
else
+ {
type2 = exp.op.exp2.expType;
+ if(type2) type2.refCount++;
+ }
}
dummy.kind = voidType;
exp.expType = Type
{
refCount = 1;
- kind = intType;
+ kind = intSizeType;
};
exp.isConstant = true;
}
if(!exp.op.exp1.expType)
ProcessExpressionType(exp.op.exp1);
else
- CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+ CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
FreeType(exp.op.exp1.expType);
exp.op.exp1.expType = MkClassType("bool");
exp.op.exp1.expType.truth = true;
if(!exp.op.exp2.expType)
ProcessExpressionType(exp.op.exp2);
else
- CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+ CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
FreeType(exp.op.exp2.expType);
exp.op.exp2.expType = MkClassType("bool");
exp.op.exp2.expType.truth = true;
// If either both are class or both are not class
((type1.kind == classType && type1._class && strcmp(type1._class.string, "String")) == (type2.kind == classType && type2._class && strcmp(type2._class.string, "String"))))
{
- if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
- exp.op.exp2.destType = type1;
- type1.refCount++;
- if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
- exp.op.exp1.destType = type2;
- type2.refCount++;
+ // Added this check for enum subtraction to result in an int type:
+ if(exp.op.op == '-' &&
+ ((type1.kind == classType && type1._class.registered && type1._class.registered.type == enumClass) ||
+ (type2.kind == classType && type2._class.registered && type2._class.registered.type == enumClass)) )
+ {
+ Type intType;
+ if(!type1._class.registered.dataType)
+ type1._class.registered.dataType = ProcessTypeString(type1._class.registered.dataTypeString, false);
+ if(!type2._class.registered.dataType)
+ type2._class.registered.dataType = ProcessTypeString(type2._class.registered.dataTypeString, false);
+
+ intType = ProcessTypeString(
+ (type1._class.registered.dataType.kind == int64Type || type2._class.registered.dataType.kind == int64Type) ? "int64" : "int", false);
+
+ if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+ if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+ exp.op.exp1.destType = intType;
+ exp.op.exp2.destType = intType;
+ intType.refCount++;
+ }
+ else
+ {
+ if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+ exp.op.exp2.destType = type1;
+ type1.refCount++;
+ if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+ exp.op.exp1.destType = type2;
+ type2.refCount++;
+ }
+
// Warning here for adding Radians + Degrees with no destination type
if(!boolResult && type1.kind == classType && (!exp.destType || exp.destType.kind != classType) &&
type1._class.registered && type1._class.registered.type == unitClass &&
MkExpMember(classExp, MkIdentifier("typeSize"))))))));
if(!exp.op.exp2.expType)
+ {
+ if(type2)
+ FreeType(type2);
type2 = exp.op.exp2.expType = ProcessTypeString("int", false);
+ type2.refCount++;
+ }
ProcessExpressionType(exp.op.exp2);
}
else if(exp.op.op == '-')
{
// Pointer Subtraction gives integer
- if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false))
+ if(MatchTypes(type1.type, type2.type, null, null, null, false, false, false, false, false))
{
exp.expType = Type
{
if(!success && exp.op.exp1.type == constantExp)
{
// If first expression is constant, try to match that first
- if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
{
if(exp.expType) FreeType(exp.expType);
exp.expType = exp.op.exp1.destType;
if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
success = true;
}
- else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+ else if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
{
if(exp.expType) FreeType(exp.expType);
exp.expType = exp.op.exp2.destType;
}
else if(!success)
{
- if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
+ if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
{
if(exp.expType) FreeType(exp.expType);
exp.expType = exp.op.exp2.destType;
if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
success = true;
}
- else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+ else if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
{
if(exp.expType) FreeType(exp.expType);
exp.expType = exp.op.exp1.destType;
exp.op.exp1.destType = type2._class.registered.dataType;
if(type2._class.registered.dataType)
type2._class.registered.dataType.refCount++;
- CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+ CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
exp.expType = type2;
if(type2) type2.refCount++;
}
exp.op.exp2.destType = type1._class.registered.dataType;
if(type1._class.registered.dataType)
type1._class.registered.dataType.refCount++;
- CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+ CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
exp.expType = type1;
if(type1) type1.refCount++;
}
exp.op.exp2.destType = type1._class.registered.dataType;
exp.op.exp2.destType.refCount++;
- CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+ CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
+ if(type2)
+ FreeType(type2);
type2 = exp.op.exp2.destType;
+ if(type2) type2.refCount++;
exp.expType = type2;
type2.refCount++;
exp.op.exp1.destType = type2._class.registered.dataType;
exp.op.exp1.destType.refCount++;
- CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+ CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
type1 = exp.op.exp1.destType;
exp.expType = type1;
type1.refCount++;
}
// TESTING THIS NEW CODE
- if(!boolResult || exp.op.op == '>' || exp.op.op == '<')
+ if(!boolResult || exp.op.op == '>' || exp.op.op == '<' || exp.op.op == GE_OP || exp.op.op == LE_OP)
{
- if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass && exp.op.exp2.expType)
+ bool op1IsEnum = type1 && type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass;
+ bool op2IsEnum = type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass;
+ if(exp.op.op == '*' || exp.op.op == '/' || exp.op.op == '-' || exp.op.op == '|' || exp.op.op == '^')
{
- if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false))
+ // Convert the enum to an int instead for these operators
+ if(op1IsEnum && exp.op.exp2.expType)
{
- if(exp.expType) FreeType(exp.expType);
- exp.expType = exp.op.exp1.expType;
- if(exp.op.exp2.expType) exp.op.exp1.expType.refCount++;
- valid = true;
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+ {
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp2.expType;
+ if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+ valid = true;
+ }
+ }
+ else if(op2IsEnum && exp.op.exp1.expType)
+ {
+ if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+ {
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp1.expType;
+ if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+ valid = true;
+ }
}
}
-
- else if(type2 && (type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass && exp.op.exp1.expType))
+ else
{
- if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false))
+ if(op1IsEnum && exp.op.exp2.expType)
{
- if(exp.expType) FreeType(exp.expType);
- exp.expType = exp.op.exp2.expType;
- if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
- valid = true;
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp2.expType, false, false))
+ {
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp1.expType;
+ if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+ valid = true;
+ }
+ }
+ else if(op2IsEnum && exp.op.exp1.expType)
+ {
+ if(CheckExpressionType(exp.op.exp2, exp.op.exp1.expType, false, false))
+ {
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp2.expType;
+ if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+ valid = true;
+ }
}
}
}
if(!valid)
{
- if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
- exp.op.exp2.destType = type1;
- type1.refCount++;
+ // Added this first part of the if here to handle 5 + Degrees { 5 } with either a base unit dest or not a unit dest type
+ if(type2 && type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == unitClass &&
+ (type1.kind != classType || !type1._class || !type1._class.registered || type1._class.registered.type != unitClass))
+ {
+ if(exp.op.exp1.destType) FreeType(exp.op.exp1.destType);
+ exp.op.exp1.destType = type2;
+ type2.refCount++;
+
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
+ {
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp1.destType;
+ if(exp.op.exp1.destType) exp.op.exp1.destType.refCount++;
+ }
+ }
+ else
+ {
+ if(exp.op.exp2.destType) FreeType(exp.op.exp2.destType);
+ exp.op.exp2.destType = type1;
+ type1.refCount++;
/*
// Maybe this was meant to be an enum...
}
*/
- if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false))
- {
- if(exp.expType) FreeType(exp.expType);
- exp.expType = exp.op.exp2.destType;
- if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
- }
- else if(type1 && type2)
- {
- char expString1[10240];
- char expString2[10240];
- char type1String[1024];
- char type2String[1024];
- expString1[0] = '\0';
- expString2[0] = '\0';
- type1String[0] = '\0';
- type2String[0] = '\0';
- if(inCompiler)
+ if(CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false))
{
- PrintExpression(exp.op.exp1, expString1);
- ChangeCh(expString1, '\n', ' ');
- PrintExpression(exp.op.exp2, expString2);
- ChangeCh(expString2, '\n', ' ');
- PrintType(exp.op.exp1.expType, type1String, false, true);
- PrintType(exp.op.exp2.expType, type2String, false, true);
+ if(exp.expType) FreeType(exp.expType);
+ exp.expType = exp.op.exp2.destType;
+ if(exp.op.exp2.destType) exp.op.exp2.destType.refCount++;
}
+ else if(type1 && type2)
+ {
+ char expString1[10240];
+ char expString2[10240];
+ char type1String[1024];
+ char type2String[1024];
+ expString1[0] = '\0';
+ expString2[0] = '\0';
+ type1String[0] = '\0';
+ type2String[0] = '\0';
+ if(inCompiler)
+ {
+ PrintExpression(exp.op.exp1, expString1);
+ ChangeCh(expString1, '\n', ' ');
+ PrintExpression(exp.op.exp2, expString2);
+ ChangeCh(expString2, '\n', ' ');
+ PrintType(exp.op.exp1.expType, type1String, false, true);
+ PrintType(exp.op.exp2.expType, type2String, false, true);
+ }
- Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
+ Compiler_Warning($"incompatible expressions %s (%s) and %s (%s)\n", expString1, type1String, expString2, type2String);
- if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
- {
- exp.expType = exp.op.exp1.expType;
- if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
- }
- else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
- {
- exp.expType = exp.op.exp2.expType;
- if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+ if(type1.kind == classType && type1._class && type1._class.registered && type1._class.registered.type == enumClass)
+ {
+ exp.expType = exp.op.exp1.expType;
+ if(exp.op.exp1.expType) exp.op.exp1.expType.refCount++;
+ }
+ else if(type2.kind == classType && type2._class && type2._class.registered && type2._class.registered.type == enumClass)
+ {
+ exp.expType = exp.op.exp2.expType;
+ if(exp.op.exp2.expType) exp.op.exp2.expType.refCount++;
+ }
}
}
}
{
Type oldType = exp.op.exp1.expType;
exp.op.exp1.expType = null;
- if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
FreeType(oldType);
else
exp.op.exp1.expType = oldType;
}
*/
- if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false))
+ if(CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false))
{
if(exp.expType) FreeType(exp.expType);
exp.expType = exp.op.exp1.destType;
exp.op.exp1.destType = type2._class.registered.dataType;
if(type2._class.registered.dataType)
type2._class.registered.dataType.refCount++;
- CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false);
+ CheckExpressionType(exp.op.exp1, exp.op.exp1.destType, false, false);
}
if(exp.op.op == '!')
{
exp.op.exp2.destType = type1._class.registered.dataType;
if(type1._class.registered.dataType)
type1._class.registered.dataType.refCount++;
- CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false);
+ CheckExpressionType(exp.op.exp2, exp.op.exp2.destType, false, false);
}
exp.expType = type1;
if(type1) type1.refCount++;
yylloc = oldyylloc;
FreeType(dummy);
+ if(type2)
+ FreeType(type2);
break;
}
case bracketsExp:
if(!e.next)
{
FreeType(e.destType);
+ e.opDestType = exp.opDestType;
e.destType = exp.destType;
if(e.destType) { exp.destType.refCount++; e.destType.count++; inced = true; }
}
if(exp.index.index && exp.index.index->last)
{
- ((Expression)exp.index.index->last).destType = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+ Type type = ProcessTypeString(_class.templateArgs[1].dataTypeString, false);
+
+ if(type.kind == classType) type.constant = true;
+ else if(type.kind == pointerType)
+ {
+ Type t = type;
+ while(t.kind == pointerType) t = t.type;
+ t.constant = true;
+ }
+
+ ((Expression)exp.index.index->last).destType = type;
}
}
}
}
if(curParam && _class.templateArgs[id].dataTypeString)
{
+ bool constant = type.constant;
ClassTemplateArgument arg = _class.templateArgs[id];
{
Context context = SetupTemplatesContext(_class);
templatedType = ProcessTypeString(arg.dataTypeString, false);
FinishTemplatesContext(context);
}
+
+ if(templatedType.kind == classType && constant) templatedType.constant = true;
+ else if(templatedType.kind == pointerType)
+ {
+ Type t = templatedType.type;
+ while(t.kind == pointerType) t = t.type;
+ if(constant) t.constant = constant;
+ }
+
e.destType = templatedType;
if(templatedType)
{
Expression exp;
char * string = PrintHexUInt64(arg.expression.ui64);
exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+ delete string;
ProcessExpressionType(exp);
ComputeExpression(exp);
// Prioritize properties over data members otherwise
else
{
+ bool useMemberForNonConst = false;
// First look for Public Members (Unless class specifier is provided, which skips public priority)
if(!id.classSym)
{
prop = eClass_FindProperty(_class, id.string, null);
- if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+ useMemberForNonConst = prop && exp.destType &&
+ ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+ !strncmp(prop.dataTypeString, "const ", 6);
+
+ if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
member = eClass_FindDataMember(_class, id.string, null, null, null);
}
- if(!prop && !member)
+ if((!prop || useMemberForNonConst) && !member)
{
- method = eClass_FindMethod(_class, id.string, null);
+ method = useMemberForNonConst ? null : eClass_FindMethod(_class, id.string, null);
if(!method)
{
prop = eClass_FindProperty(_class, id.string, privateModule);
- if(!id._class || !id._class.name || strcmp(id._class.name, "property"))
+
+ useMemberForNonConst |= prop && exp.destType &&
+ ( (exp.destType.kind == classType && !exp.destType.constant) || ((exp.destType.kind == pointerType || exp.destType.kind == arrayType) && exp.destType.type && !exp.destType.type.constant) ) &&
+ !strncmp(prop.dataTypeString, "const ", 6);
+
+ if(useMemberForNonConst || !id._class || !id._class.name || strcmp(id._class.name, "property"))
member = eClass_FindDataMember(_class, id.string, privateModule, null, null);
}
}
if(member && prop)
{
- if(member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class))
+ if(useMemberForNonConst || (member._class != prop._class && !id._class && eClass_IsDerived(member._class, prop._class)))
prop = null;
else
member = null;
FreeExpContents(exp);
exp.type = identifierExp;
exp.identifier = MkIdentifier("class");
- ProcessExpressionType(exp);
+ FreeType(exp.expType);
+ exp.expType = MkClassType("ecere::com::Class");
return;
}
yylloc = exp.member.member.loc;
{
ClassTemplateArgument arg = tClass.templateArgs[id];
Context context = SetupTemplatesContext(tClass);
+ bool constant = exp.expType.constant;
/*if(!arg.dataType)
arg.dataType = ProcessTypeString(arg.dataTypeString, false);*/
FreeType(exp.expType);
+
exp.expType = ProcessTypeString(arg.dataTypeString, false);
+ if(exp.expType.kind == classType && constant) exp.expType.constant = true;
+ else if(exp.expType.kind == pointerType)
+ {
+ Type t = exp.expType.type;
+ while(t.kind == pointerType) t = t.type;
+ if(constant) t.constant = constant;
+ }
if(exp.expType)
{
if(exp.expType.kind == thisClassType)
if(!exp.destType)
{
exp.destType = ProcessTypeString(arg.dataTypeString, false);
+ if(exp.destType.kind == classType && constant) exp.destType.constant = true;
+ else if(exp.destType.kind == pointerType)
+ {
+ Type t = exp.destType.type;
+ while(t.kind == pointerType) t = t.type;
+ if(constant) t.constant = constant;
+ }
+
//exp.destType.refCount++;
if(exp.destType.kind == thisClassType)
Expression exp;
char * string = PrintHexUInt64(arg.expression.ui64);
exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
+ delete string;
ProcessExpressionType(exp);
ComputeExpression(exp);
exp.expType = Type
{
refCount = 1;
- kind = intType;
+ kind = intSizeType;
};
// exp.isConstant = true;
break;
exp.expType = Type
{
refCount = 1;
- kind = intType;
+ kind = intSizeType;
};
exp.isConstant = true;
FreeType(exp.cast.exp.destType);
exp.cast.exp.destType = type;
type.refCount++;
+ type.casted = true;
ProcessExpressionType(exp.cast.exp);
+ type.casted = false;
type.count = 0;
exp.expType = type;
//type.refCount++;
case arrayExp:
{
Type type = null;
- char * typeString = null;
+ const char * typeString = null;
char typeStringBuf[1024];
if(exp.destType && exp.destType.kind == classType && exp.destType._class && exp.destType._class.registered &&
exp.destType._class.registered != containerClass && eClass_IsDerived(exp.destType._class.registered, containerClass))
else
{
// if(!MatchType(e.expType, type, null, null, null, false, false, false))
- if(!MatchTypeExpression(e, type, null, false))
+ if(!MatchTypeExpression(e, type, null, false, true))
{
FreeType(type);
type = e.expType;
if(e.expType)
{
//if(!MatchTypes(e.expType, type, null, null, null, false, false, false))
- if(!MatchTypeExpression(e, type, null, false))
+ if(!MatchTypeExpression(e, type, null, false, true))
{
FreeType(e.expType);
e.expType = null;
if(exp.destType && (exp.destType.kind == voidType || exp.destType.kind == dummyType) );
else if(exp.destType && !exp.destType.keepCast)
{
- if(!CheckExpressionType(exp, exp.destType, false))
+ if(!CheckExpressionType(exp, exp.destType, false, !exp.destType.casted))
{
if(!exp.destType.count || unresolved)
{
if(inCompiler) { PrintExpression(exp, expString); ChangeCh(expString, '\n', ' '); }
#ifdef _DEBUG
- CheckExpressionType(exp, exp.destType, false);
+ CheckExpressionType(exp, exp.destType, false, true);
#endif
// Flex & Bison generate code that triggers this, so we ignore it for a quiet sdk build:
if(!sourceFile || (strcmp(sourceFile, "src\\lexer.ec") && strcmp(sourceFile, "src/lexer.ec") && strcmp(sourceFile, "src\\grammar.ec") && strcmp(sourceFile, "src/grammar.ec")))
qualifiers = MkListOne(MkSpecifier(VOID));
declarator = MkDeclaratorPointer(MkPointer(null,null), d);
};
+ if(d.type != pointerDeclarator)
+ newParam.qualifiers->Insert(null, MkSpecifier(CONST));
FreeList(param.qualifiers, FreeSpecifier);
FreeList(param.qualifiers, FreeSpecifier);
param.qualifiers = MkListOne(MkSpecifier(VOID));
+ if(d.type != pointerDeclarator)
+ param.qualifiers->Insert(null, MkSpecifier(CONST));
param.declarator = MkDeclaratorPointer(MkPointer(null,null), d);
}
else if(spec.specifier == THISCLASS)
Context prevContext = curContext;
if(!stmt.compound.isSwitch)
- {
curCompound = stmt;
- curContext = stmt.compound.context;
- }
+ curContext = stmt.compound.context;
if(stmt.compound.declarations)
{
(((Expression)exp->last).type == ExpressionType::arrayExp ||
(((Expression)exp->last).type == castExp && ((Expression)exp->last).cast.exp.type == ExpressionType::arrayExp));
Expression arrayExp;
- char * typeString = null;
+ const char * typeString = null;
int builtinCount = 0;
for(e = exp ? exp->first : null; e; e = e.next)
Class _class = source ? source._class.registered : null;
Symbol symbol;
Expression expIt = null;
- bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false, isAVLTree = false;
+ bool isMap = false, isArray = false, isLinkList = false, isList = false, isCustomAVLTree = false; //, isAVLTree = false;
Class arrayClass = eSystem_FindClass(privateModule, "Array");
Class linkListClass = eSystem_FindClass(privateModule, "LinkList");
Class customAVLTreeClass = eSystem_FindClass(privateModule, "CustomAVLTree");
if(source && eClass_IsDerived(source._class.registered, customAVLTreeClass))
{
Class mapClass = eSystem_FindClass(privateModule, "Map");
- Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
+ //Class avlTreeClass = eSystem_FindClass(privateModule, "AVLTree");
isCustomAVLTree = true;
- if(eClass_IsDerived(source._class.registered, avlTreeClass))
+ /*if(eClass_IsDerived(source._class.registered, avlTreeClass))
isAVLTree = true;
- else if(eClass_IsDerived(source._class.registered, mapClass))
+ else */if(eClass_IsDerived(source._class.registered, mapClass))
isMap = true;
}
else if(source && eClass_IsDerived(source._class.registered, arrayClass)) isArray = true;
else
{
// if(!MatchType(e.expType, type, null, null, null, false, false, false))
- if(!MatchTypeExpression(e, type, null, false))
+ if(!MatchTypeExpression(e, type, null, false, true))
{
FreeType(type);
type = e.expType;
if(e.expType)
{
//if(!MatchTypes(e.expType, type, null, null, null, false, false, false, false))
- if(!MatchTypeExpression(e, type, null, false))
+ if(!MatchTypeExpression(e, type, null, false, true))
{
FreeType(e.expType);
e.expType = null;
ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_Watch")), args));
}
else
- Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+ Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
}
}
}
ListAdd(stmt.expressions, MkExpCall(MkExpIdentifier(MkIdentifier("ecere::com::eInstance_StopWatching")), args));
}
else
- Compiler_Error($"Property %s not found in class %s\n", prop.name, _class.fullName);
+ Compiler_Error($"Property %s not found in class %s\n", propID.string, _class.fullName);
}
}
}
}
-void DeclareFunctionUtil(String s)
+void DeclareFunctionUtil(const String s)
{
GlobalFunction function = eSystem_FindFunction(privateModule, s);
if(function)
DeclareFunctionUtil("eSystem_New0");
DeclareFunctionUtil("eSystem_Renew");
DeclareFunctionUtil("eSystem_Renew0");
+ DeclareFunctionUtil("eSystem_Delete");
DeclareFunctionUtil("eClass_GetProperty");
+ DeclareFunctionUtil("eClass_SetProperty");
+ DeclareFunctionUtil("eInstance_FireSelfWatchers");
+ DeclareFunctionUtil("eInstance_SetMethod");
+ DeclareFunctionUtil("eInstance_IncRef");
+ DeclareFunctionUtil("eInstance_StopWatching");
+ DeclareFunctionUtil("eInstance_Watch");
+ DeclareFunctionUtil("eInstance_FireWatchers");
DeclareStruct("ecere::com::Class", false);
DeclareStruct("ecere::com::Instance", false);
else if(external.type == declarationExternal)
{
currentClass = null;
- ProcessDeclaration(external.declaration);
+ if(external.declaration)
+ ProcessDeclaration(external.declaration);
}
else if(external.type == classExternal)
{
}
currentClass = null;
thisNameSpace = null;
+ curExternal = null;
delete temp.symbol;
delete temp;