diff options
| -rw-r--r-- | source/core/core.natvis | 4 | ||||
| -rw-r--r-- | source/core/slang-io.cpp | 45 | ||||
| -rw-r--r-- | source/core/slang-string.cpp | 251 | ||||
| -rw-r--r-- | source/core/slang-string.h | 658 | ||||
| -rw-r--r-- | source/core/smart-pointer.h | 593 | ||||
| -rw-r--r-- | source/core/stream.h | 2 | ||||
| -rw-r--r-- | source/core/text-io.cpp | 6 | ||||
| -rw-r--r-- | source/core/text-io.h | 4 | ||||
| -rw-r--r-- | source/slang/check.cpp | 64 | ||||
| -rw-r--r-- | source/slang/lexer.cpp | 3 | ||||
| -rw-r--r-- | source/slang/options.cpp | 6 | ||||
| -rw-r--r-- | source/slang/parameter-binding.cpp | 4 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-stdlib.cpp | 2 | ||||
| -rw-r--r-- | source/slang/syntax.h | 29 | ||||
| -rw-r--r-- | source/slangc/main.cpp | 2 | ||||
| -rw-r--r-- | tools/slang-test/main.cpp | 4 | ||||
| -rw-r--r-- | tools/slang-test/os.cpp | 4 |
18 files changed, 810 insertions, 875 deletions
diff --git a/source/core/core.natvis b/source/core/core.natvis index 19c6db395..3d9ac702e 100644 --- a/source/core/core.natvis +++ b/source/core/core.natvis @@ -3,8 +3,8 @@ <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <Type Name="Slang::String"> - <DisplayString>{buffer.pointer,s}</DisplayString> - <StringView>buffer.pointer,s</StringView> + <DisplayString>{((char*) (buffer.pointer+1)),s}</DisplayString> + <StringView>((char*) (buffer.pointer+1)),s</StringView> </Type> <Type Name="Slang::ArrayView<*>"> diff --git a/source/core/slang-io.cpp b/source/core/slang-io.cpp index dc2793fc4..684fed0a1 100644 --- a/source/core/slang-io.cpp +++ b/source/core/slang-io.cpp @@ -40,24 +40,46 @@ namespace Slang sb.Append(newExt); return sb.ProduceString(); } + + static UInt findLastSeparator(String const& path) + { + UInt slashPos = path.LastIndexOf('/'); + UInt backslashPos = path.LastIndexOf('\\'); + + if (slashPos == -1) return backslashPos; + if (backslashPos == -1) return slashPos; + + UInt pos = slashPos; + if (backslashPos > slashPos) + pos = backslashPos; + + return pos; + } + String Path::GetFileName(const String & path) { - int pos = path.LastIndexOf('/'); - pos = Math::Max(path.LastIndexOf('\\'), pos) + 1; - return path.SubString(pos, path.Length()-pos); + UInt pos = findLastSeparator(path); + if (pos != -1) + { + pos = pos + 1; + return path.SubString(pos, path.Length() - pos); + } + else + { + return path; + } } String Path::GetFileNameWithoutEXT(const String & path) { - int pos = path.LastIndexOf('/'); - pos = Math::Max(path.LastIndexOf('\\'), pos) + 1; - int dotPos = path.LastIndexOf('.'); - if (dotPos <= pos) - dotPos = path.Length(); - return path.SubString(pos, dotPos - pos); + String fileName = GetFileName(path); + int dotPos = fileName.LastIndexOf('.'); + if (dotPos == -1) + return fileName; + return fileName.SubString(0, dotPos); } String Path::GetFileExt(const String & path) { - int dotPos = path.LastIndexOf('.'); + UInt dotPos = path.LastIndexOf('.'); if (dotPos != -1) return path.SubString(dotPos+1, path.Length()-dotPos-1); else @@ -65,8 +87,7 @@ namespace Slang } String Path::GetDirectoryName(const String & path) { - int pos = path.LastIndexOf('/'); - pos = Math::Max(path.LastIndexOf('\\'), pos); + UInt pos = findLastSeparator(path); if (pos != -1) return path.SubString(0, pos); else diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index b7eaadcb3..3b9bcc87f 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -3,42 +3,76 @@ namespace Slang { + // OSString + + OSString::OSString() + : beginData(0) + , endData(0) + {} + + OSString::OSString(wchar_t* begin, wchar_t* end) + : beginData(begin) + , endData(end) + {} + + OSString::~OSString() + { + if (beginData) + { + delete[] beginData; + } + } + + static const wchar_t kEmptyOSString[] = { 0 }; + + wchar_t const* OSString::begin() const + { + return beginData ? beginData : kEmptyOSString; + } + + wchar_t const* OSString::end() const + { + return endData ? endData : kEmptyOSString; + } + + // StringSlice + + StringSlice::StringSlice() + : representation(0) + , beginIndex(0) + , endIndex(0) + {} + + StringSlice::StringSlice(String const& str, UInt beginIndex, UInt endIndex) + : representation(str.buffer) + , beginIndex(beginIndex) + , endIndex(endIndex) + {} + + + // + _EndLine EndLine; - String StringConcat(const char * lhs, int leftLen, const char * rhs, int rightLen) - { - String res; - res.length = leftLen + rightLen; - res.buffer = new char[res.length + 1]; - strcpy_s(res.buffer.Ptr(), res.length + 1, lhs); - strcpy_s(res.buffer + leftLen, res.length + 1 - leftLen, rhs); - return res; - } - String operator+(const char * op1, const String & op2) - { - if(!op2.buffer) - return String(op1); - return StringConcat(op1, (int)strlen(op1), op2.buffer.Ptr(), op2.length); + String operator+(const char * op1, const String & op2) + { + String result(op1); + result.append(op2); + return result; } String operator+(const String & op1, const char * op2) { - if(!op1.buffer) - return String(op2); - - return StringConcat(op1.buffer.Ptr(), op1.length, op2, (int)strlen(op2)); + String result(op1); + result.append(op2); + return result; } String operator+(const String & op1, const String & op2) { - if(!op1.buffer && !op2.buffer) - return String(); - else if(!op1.buffer) - return String(op2); - else if(!op2.buffer) - return String(op1); - - return StringConcat(op1.buffer.Ptr(), op1.length, op2.buffer.Ptr(), op2.length); + String result(op1); + result.append(op2); + return result; } int StringToInt(const String & str, int radix) @@ -64,6 +98,7 @@ namespace Slang return strtof(str.Buffer(), NULL); } +#if 0 String String::ReplaceAll(String src, String dst) const { String rs = *this; @@ -77,6 +112,7 @@ namespace Slang } return rs; } +#endif String String::FromWString(const wchar_t * wstr) { @@ -113,51 +149,150 @@ namespace Slang return String(buf); } - const wchar_t * String::ToWString(int * len) const + OSString String::ToWString(int* outLength) const { if (!buffer) { - if (len) - *len = 0; - return L""; + return OSString(); } else { - if (wcharBuffer) - { - if (len) - *len = (int)wcslen(wcharBuffer); - return wcharBuffer; - } List<char> buf; Slang::Encoding::UTF16->GetBytes(buf, *this); - if (len) - *len = buf.Count() / sizeof(wchar_t); + + auto length = buf.Count() / sizeof(wchar_t); + if (outLength) + *outLength = length; + buf.Add(0); buf.Add(0); - const_cast<String*>(this)->wcharBuffer = (wchar_t*)buf.Buffer(); + + wchar_t* beginData = (wchar_t*)buf.Buffer(); + wchar_t* endData = beginData + length; + buf.ReleaseBuffer(); - return wcharBuffer; + + return OSString(beginData, endData); } } - String String::PadLeft(char ch, int pLen) - { - StringBuilder sb; - for (int i = 0; i < pLen - this->length; i++) - sb << ch; - for (int i = 0; i < this->length; i++) - sb << buffer[i]; - return sb.ProduceString(); - } + // - String String::PadRight(char ch, int pLen) - { - StringBuilder sb; - for (int i = 0; i < this->length; i++) - sb << buffer[i]; - for (int i = 0; i < pLen - this->length; i++) - sb << ch; - return sb.ProduceString(); - } + void String::ensureUniqueStorageWithCapacity(UInt requiredCapacity) + { + if (buffer && buffer->isUniquelyReferenced() && buffer->capacity >= requiredCapacity) + return; + + UInt newCapacity = buffer ? 2*buffer->capacity : 16; + if (newCapacity < requiredCapacity) + { + newCapacity = requiredCapacity; + } + + UInt length = getLength(); + StringRepresentation* newRepresentation = StringRepresentation::createWithCapacityAndLength(newCapacity, length); + + if (buffer) + { + memcpy(newRepresentation->getData(), buffer->getData(), length + 1); + } + + buffer = newRepresentation; + } + + char* String::prepareForAppend(UInt count) + { + auto oldLength = getLength(); + auto newLength = oldLength + count; + ensureUniqueStorageWithCapacity(newLength); + return getData() + oldLength; + } + + + void String::append(const char* textBegin, char const* textEnd) + { + auto oldLength = getLength(); + auto textLength = textEnd - textBegin; + + auto newLength = oldLength + textLength; + + ensureUniqueStorageWithCapacity(newLength); + + memcpy(getData() + oldLength, textBegin, textLength); + getData()[newLength] = 0; + buffer->length = newLength; + } + + void String::append(char const* str) + { + if (str) + { + append(str, str + strlen(str)); + } + } + + void String::append(char chr) + { + append(&chr, &chr + 1); + } + + void String::append(String const& str) + { + if (!buffer) + { + buffer = str.buffer; + return; + } + + append(str.begin(), str.end()); + } + + void String::append(StringSlice const& slice) + { + append(slice.begin(), slice.end()); + } + + void String::append(int value, int radix) + { + enum { kCount = 33 }; + char* data = prepareForAppend(kCount); + auto count = IntToAscii(data, value, radix); + ReverseInternalAscii(data, count); + buffer->length += count; + } + + void String::append(unsigned int value, int radix) + { + enum { kCount = 33 }; + char* data = prepareForAppend(kCount); + auto count = IntToAscii(data, value, radix); + ReverseInternalAscii(data, count); + buffer->length += count; + } + + void String::append(long long value, int radix) + { + enum { kCount = 65 }; + char* data = prepareForAppend(kCount); + auto count = IntToAscii(data, value, radix); + ReverseInternalAscii(data, count); + buffer->length += count; + } + + + void String::append(float val, const char * format) + { + enum { kCount = 128 }; + char* data = prepareForAppend(kCount); + sprintf_s(data, kCount, format, val); + buffer->length += strnlen_s(data, kCount); + } + + void String::append(double val, const char * format) + { + enum { kCount = 128 }; + char* data = prepareForAppend(kCount); + sprintf_s(data, kCount, format, val); + buffer->length += strnlen_s(data, kCount); + } } diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 448b351aa..8294d4bc3 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -8,6 +8,8 @@ #include "hash.h" #include "secure-crt.h" +#include <new> + namespace Slang { class _EndLine @@ -58,35 +60,182 @@ namespace Slang return (((unsigned char)ch) & 0xC0) == 0x80; } + // A `StringRepresentation` provides the backing storage for + // all reference-counted string-related types. + class StringRepresentation : public RefObject + { + public: + UInt length; + UInt capacity; + + UInt getLength() + { + return length; + } + + char* getData() + { + return (char*) (this + 1); + } + + static StringRepresentation* createWithCapacityAndLength(UInt capacity, UInt length) + { + assert(capacity >= length); + void* allocation = operator new(sizeof(StringRepresentation) + capacity + 1); + StringRepresentation* obj = new(allocation) StringRepresentation(); + obj->capacity = capacity; + obj->length = length; + obj->getData()[length] = 0; + return obj; + } + + static StringRepresentation* createWithCapacity(UInt capacity) + { + return createWithCapacityAndLength(capacity, 0); + } + + static StringRepresentation* createWithLength(UInt length) + { + return createWithCapacityAndLength(length, length); + } + + StringRepresentation* cloneWithCapacity(UInt newCapacity) + { + StringRepresentation* newObj = createWithCapacityAndLength(newCapacity, length); + memcpy(getData(), newObj->getData(), length + 1); + return newObj; + } + + StringRepresentation* clone() + { + return cloneWithCapacity(length); + } + + StringRepresentation* ensureCapacity(UInt required) + { + if (capacity >= required) return this; + + UInt newCapacity = capacity; + if (!newCapacity) newCapacity = 16; // TODO: figure out good value for minimum capacity + + while (newCapacity < required) + { + newCapacity = 2 * newCapacity; + } + + return cloneWithCapacity(newCapacity); + } + }; + + class String; + + struct UnownedStringSlice + { + public: + + char const* begin() const + { + return beginData; + } + + char const* end() const + { + return endData; + } + + private: + char const* beginData; + char const* endData; + }; + + struct StringSlice + { + public: + StringSlice(); + + StringSlice(String const& str, UInt beginIndex, UInt endIndex); + + UInt getLength() const + { + return endIndex - beginIndex; + } + + char const* begin() const + { + return representation ? representation->getData() + beginIndex : ""; + } + + char const* end() const + { + return begin() + getLength(); + } + + private: + RefPtr<StringRepresentation> representation; + UInt beginIndex; + UInt endIndex; + + friend class String; + + StringSlice(RefPtr<StringRepresentation> const& representation, UInt beginIndex, UInt endIndex) + : representation(representation) + , beginIndex(beginIndex) + , endIndex(endIndex) + {} + }; + + /// String as expected by underlying platform APIs + class OSString + { + public: + OSString(); + OSString(wchar_t* begin, wchar_t* end); + ~OSString(); + + operator wchar_t const*() const + { + return begin(); + } + + wchar_t const* begin() const; + wchar_t const* end() const; + + private: + wchar_t* beginData; + wchar_t* endData; + }; + /*! @brief Represents a UTF-8 encoded string. */ class String { + friend struct StringSlice; friend class StringBuilder; private: - RefPtr<char, RefPtrArrayDestructor> buffer; - wchar_t * wcharBuffer = nullptr; - int length = 0; - void Free() - { - if (buffer) - buffer = 0; - if (wcharBuffer) - delete[] wcharBuffer; - buffer = 0; - wcharBuffer = 0; - length = 0; - } - public: - static String FromBuffer(RefPtr<char, RefPtrArrayDestructor> buffer, int len) - { - String rs; - rs.buffer = buffer; - rs.length = len; - return rs; - } + + + char* getData() const + { + return buffer ? buffer->getData() : ""; + } + + UInt getLength() const + { + return buffer ? buffer->getLength() : 0; + } + + void ensureUniqueStorageWithCapacity(UInt capacity); + char* prepareForAppend(UInt count); + + RefPtr<StringRepresentation> buffer; + + String(StringRepresentation* buffer) + : buffer(buffer) + {} + + public: static String FromWString(const wchar_t * wstr); static String FromWString(const wchar_t * wstr, const wchar_t * wend); static String FromWChar(const wchar_t ch); @@ -94,409 +243,376 @@ namespace Slang String() { } + const char * begin() const { - return buffer.Ptr(); + return getData(); } const char * end() const { - return buffer.Ptr() + length; + return getData() + getLength(); } + + void append(int value, int radix = 10); + void append(unsigned int value, int radix = 10); + void append(long long value, int radix = 10); + void append(float val, const char * format = "%g"); + void append(double val, const char * format = "%g"); + + void append(char const* str); + void append(const char* textBegin, char const* textEnd); + void append(char chr); + void append(String const& str); + void append(StringSlice const& slice); + String(int val, int radix = 10) { - buffer = new char[33]; - length = IntToAscii(buffer.Ptr(), val, radix); - ReverseInternalAscii(buffer.Ptr(), length); + append(val, radix); +#if 0 + buffer = StringRepresentation::createWithLength(33); + buffer->length = IntToAscii(getData(), val, radix); + ReverseInternalAscii(getData(), getLength()); +#endif } String(unsigned int val, int radix = 10) { - buffer = new char[33]; - length = IntToAscii(buffer.Ptr(), val, radix); - ReverseInternalAscii(buffer.Ptr(), length); + append(val, radix); +#if 0 + buffer = StringRepresentation::createWithLength(33); + buffer->length = IntToAscii(getData(), val, radix); + ReverseInternalAscii(getData(), getLength()); +#endif } String(long long val, int radix = 10) { - buffer = new char[65]; - length = IntToAscii(buffer.Ptr(), val, radix); - ReverseInternalAscii(buffer.Ptr(), length); + append(val, radix); +#if 0 + buffer = StringRepresentation::createWithLength(65); + buffer->length = IntToAscii(getData(), val, radix); + ReverseInternalAscii(getData(), getLength()); +#endif } String(float val, const char * format = "%g") { - buffer = new char[128]; - sprintf_s(buffer.Ptr(), 128, format, val); - length = (int)strnlen_s(buffer.Ptr(), 128); + append(val, format); +#if 0 + buffer = StringRepresentation::createWithLength(128); + sprintf_s(getData(), 128, format, val); + buffer->length = (int)strnlen_s(begin(), 128); +#endif } String(double val, const char * format = "%g") { - buffer = new char[128]; - sprintf_s(buffer.Ptr(), 128, format, val); - length = (int)strnlen_s(buffer.Ptr(), 128); + append(val, format); +#if 0 + buffer = StringRepresentation::createWithLength(128); + sprintf_s(getData(), 128, format, val); + buffer->length = (int)strnlen_s(begin(), 128); +#endif } String(const char * str) { + append(str); +#if 0 if (str) { - length = (int)strlen(str); - buffer = new char[length + 1]; - memcpy(buffer.Ptr(), str, length + 1); + buffer = StringRepresentation::createWithLength(strlen(str)); + memcpy(buffer.Ptr(), str, getLength() + 1); } +#endif } String(const char* textBegin, char const* textEnd) { + append(textBegin, textEnd); +#if 0 if (textBegin != textEnd) { - length = (int)(textEnd - textBegin); - buffer = new char[length + 1]; - memcpy(buffer.Ptr(), textBegin, length + 1); - buffer.Ptr()[length] = 0; + buffer = StringRepresentation::createWithLength(textEnd - textBegin); + memcpy(buffer.Ptr(), textBegin, getLength()); + buffer->getData()[getLength()] = 0; } +#endif } String(char chr) { + append(chr); +#if 0 if (chr) { - length = 1; - buffer = new char[2]; - buffer[0] = chr; - buffer[1] = '\0'; + buffer = StringRepresentation::createWithLength(1); + buffer->getData()[0] = chr; + buffer->getData()[1] = 0; } +#endif } - String(const String & str) + String(String const& str) { + buffer = str.buffer; +#if 0 this->operator=(str); +#endif } String(String&& other) { - this->operator=(static_cast<String&&>(other)); + buffer = _Move(other.buffer); } + + String(StringSlice const& slice) + { + append(slice); + } + ~String() { - Free(); + buffer = 0; } + String & operator=(const String & str) { - if (str.buffer == buffer) - return *this; - Free(); - if (str.buffer) - { - length = str.length; - buffer = str.buffer; - wcharBuffer = 0; - } + buffer = str.buffer; return *this; } String & operator=(String&& other) { - if (this != &other) - { - Free(); - buffer = _Move(other.buffer); - length = other.length; - wcharBuffer = other.wcharBuffer; - other.buffer = 0; - other.length = 0; - other.wcharBuffer = 0; - } - return *this; + buffer = _Move(other.buffer); + return *this; } - char operator[](int id) const + char operator[](UInt id) const { #if _DEBUG - if (id < 0 || id >= length) + if (id < 0 || id >= getLength()) throw "Operator[]: index out of range."; #endif - return buffer.Ptr()[id]; + return begin()[id]; } - friend String StringConcat(const char * lhs, int leftLen, const char * rhs, int rightLen); friend String operator+(const char*op1, const String & op2); friend String operator+(const String & op1, const char * op2); friend String operator+(const String & op1, const String & op2); - String TrimStart() const + StringSlice TrimStart() const { if (!buffer) - return *this; - int startIndex = 0; - while (startIndex < length && - (buffer[startIndex] == ' ' || buffer[startIndex] == '\t' || buffer[startIndex] == '\r' || buffer[startIndex] == '\n')) + return StringSlice(); + UInt startIndex = 0; + while (startIndex < getLength() && + (getData()[startIndex] == ' ' || getData()[startIndex] == '\t' || getData()[startIndex] == '\r' || getData()[startIndex] == '\n')) startIndex++; - return String(buffer + startIndex); + return StringSlice(buffer, startIndex, getLength()); } - String TrimEnd() const + StringSlice TrimEnd() const { if (!buffer) - return *this; + return StringSlice(); - int endIndex = length - 1; - while (endIndex >= 0 && - (buffer[endIndex] == ' ' || buffer[endIndex] == '\t' || buffer[endIndex] == '\r' || buffer[endIndex] == '\n')) + UInt endIndex = getLength(); + while (endIndex > 0 && + (getData()[endIndex-1] == ' ' || getData()[endIndex-1] == '\t' || getData()[endIndex-1] == '\r' || getData()[endIndex-1] == '\n')) endIndex--; - String res; - res.length = endIndex + 1; - res.buffer = new char[endIndex + 2]; - strncpy_s(res.buffer.Ptr(), endIndex + 2, buffer.Ptr(), endIndex + 1); - return res; + + return StringSlice(buffer, 0, endIndex); } - String Trim() const + StringSlice Trim() const { if (!buffer) - return *this; + return StringSlice(); - int startIndex = 0; - while (startIndex < length && - (buffer[startIndex] == ' ' || buffer[startIndex] == '\t')) + UInt startIndex = 0; + while (startIndex < getLength() && + (getData()[startIndex] == ' ' || getData()[startIndex] == '\t')) startIndex++; - int endIndex = length - 1; - while (endIndex >= startIndex && - (buffer[endIndex] == ' ' || buffer[endIndex] == '\t')) + UInt endIndex = getLength(); + while (endIndex > startIndex && + (getData()[endIndex-1] == ' ' || getData()[endIndex-1] == '\t')) endIndex--; - String res; - res.length = endIndex - startIndex + 1; - res.buffer = new char[res.length + 1]; - memcpy(res.buffer.Ptr(), buffer + startIndex, res.length); - res.buffer[res.length] = '\0'; - return res; + return StringSlice(buffer, startIndex, endIndex); } - String SubString(int id, int len) const + StringSlice SubString(UInt id, UInt len) const { if (len == 0) - return ""; - if (id + len > length) - len = length - id; + return StringSlice(); + + if (id + len > getLength()) + len = getLength() - id; #if _DEBUG - if (id < 0 || id >= length || (id + len) > length) + if (id < 0 || id >= getLength() || (id + len) > getLength()) throw "SubString: index out of range."; if (len < 0) throw "SubString: length less than zero."; #endif - String res; - res.buffer = new char[len + 1]; - res.length = len; - strncpy_s(res.buffer.Ptr(), len + 1, buffer + id, len); - res.buffer[len] = 0; - return res; + return StringSlice(buffer, id, id + len); } - const char * Buffer() const + char const* Buffer() const { - if (buffer) - return buffer.Ptr(); - else - return ""; + return getData(); } - const wchar_t * ToWString(int * len = 0) const; + OSString ToWString(int* len = 0) const; bool Equals(const String & str, bool caseSensitive = true) { - if (!buffer) - return (str.buffer == 0); if (caseSensitive) - return (strcmp(buffer.Ptr(), str.buffer.Ptr()) == 0); + return (strcmp(begin(), str.begin()) == 0); else { #ifdef _MSC_VER - return (_stricmp(buffer.Ptr(), str.buffer.Ptr()) == 0); + return (_stricmp(begin(), str.begin()) == 0); #else - return (strcasecmp(buffer.Ptr(), str.buffer.Ptr()) == 0); + return (strcasecmp(begin(), str.begin()) == 0); #endif } } bool operator==(const char * strbuffer) const { - if (!buffer) - return (strbuffer == 0 || strcmp(strbuffer, "") == 0); - if (!strbuffer) - return buffer == nullptr || strcmp(buffer.Ptr(), "") == 0; - return (strcmp(buffer.Ptr(), strbuffer) == 0); + return (strcmp(begin(), strbuffer) == 0); } bool operator==(const String & str) const { - if (!buffer) - return (str.buffer == 0 || strcmp(str.buffer.Ptr(), "") == 0); - if (!str.buffer) - return buffer == nullptr || strcmp(buffer.Ptr(), "") == 0; - return (strcmp(buffer.Ptr(), str.buffer.Ptr()) == 0); + return (strcmp(begin(), str.begin()) == 0); } bool operator!=(const char * strbuffer) const { - if (!buffer) - return (strbuffer != 0 && strcmp(strbuffer, "") != 0); - if (strbuffer == 0) - return length != 0; - return (strcmp(buffer.Ptr(), strbuffer) != 0); + return (strcmp(begin(), strbuffer) != 0); } bool operator!=(const String & str) const { - if (!buffer) - return (str.buffer != 0 && strcmp(str.buffer.Ptr(), "") != 0); - if (str.buffer.Ptr() == 0) - return length != 0; - return (strcmp(buffer.Ptr(), str.buffer.Ptr()) != 0); + return (strcmp(begin(), str.begin()) != 0); } bool operator>(const String & str) const { - if (!buffer) - return false; - if (!str.buffer) - return buffer.Ptr() != nullptr && length != 0; - return (strcmp(buffer.Ptr(), str.buffer.Ptr()) > 0); + return (strcmp(begin(), str.begin()) > 0); } bool operator<(const String & str) const { - if (!buffer) - return (str.buffer != 0); - if (!str.buffer) - return false; - return (strcmp(buffer.Ptr(), str.buffer.Ptr()) < 0); + return (strcmp(begin(), str.begin()) < 0); } bool operator>=(const String & str) const { - if (!buffer) - return (str.buffer == 0); - if (!str.buffer) - return length == 0; - int res = strcmp(buffer.Ptr(), str.buffer.Ptr()); - return (res > 0 || res == 0); + return (strcmp(begin(), str.begin()) >= 0); } bool operator<=(const String & str) const { - if (!buffer) - return true; - if (!str.buffer) - return length > 0; - int res = strcmp(buffer.Ptr(), str.buffer.Ptr()); - return (res < 0 || res == 0); + return (strcmp(begin(), str.begin()) <= 0); } String ToUpper() const { - if (!buffer) - return *this; - String res; - res.length = length; - res.buffer = new char[length + 1]; - for (int i = 0; i <= length; i++) - res.buffer[i] = (buffer[i] >= 'a' && buffer[i] <= 'z') ? - (buffer[i] - 'a' + 'A') : buffer[i]; - return res; + String result; + for (auto c : *this) + { + int d = (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c; + result.append(d); + } + return result; } String ToLower() const { - if (!buffer) - return *this; - String res; - res.length = length; - res.buffer = new char[length + 1]; - for (int i = 0; i <= length; i++) - res.buffer[i] = (buffer[i] >= 'A' && buffer[i] <= 'Z') ? - (buffer[i] - 'A' + 'a') : buffer[i]; - return res; + String result; + for (auto c : *this) + { + int d = (c >= 'A' && c <= 'Z') ? (c - ('A' - 'a')) : c; + result.append(d); + } + return result; } - int Length() const + UInt Length() const { - return length; + return getLength(); } - int IndexOf(const char * str, int id) const // String str + UInt IndexOf(const char * str, UInt id) const // String str { - if (!buffer) - return -1; - if (id < 0 || id >= length) - return -1; - auto findRs = strstr(buffer + id, str); - int res = findRs ? (int)(findRs - buffer.Ptr()) : -1; - if (res >= 0) - return res; - else - return -1; + if (id < 0 || id >= getLength()) + return UInt(-1); + auto findRs = strstr(begin() + id, str); + UInt res = findRs ? findRs - begin() : -1; + return res; } - int IndexOf(const String & str, int id) const + UInt IndexOf(const String & str, UInt id) const { - return IndexOf(str.buffer.Ptr(), id); + return IndexOf(str.begin(), id); } - int IndexOf(const char * str) const + UInt IndexOf(const char * str) const { return IndexOf(str, 0); } - int IndexOf(const String & str) const + UInt IndexOf(const String & str) const { - return IndexOf(str.buffer.Ptr(), 0); + return IndexOf(str.begin(), 0); } - int IndexOf(char ch, int id) const + UInt IndexOf(char ch, UInt id) const { #if _DEBUG - if (id < 0 || id >= length) + if (id < 0 || id >= getLength()) throw "SubString: index out of range."; #endif if (!buffer) - return -1; - for (int i = id; i < length; i++) - if (buffer[i] == ch) + return UInt(-1); + for (UInt i = id; i < getLength(); i++) + if (getData()[i] == ch) return i; - return -1; + return UInt(-1); } - int IndexOf(char ch) const + UInt IndexOf(char ch) const { return IndexOf(ch, 0); } - int LastIndexOf(char ch) const + UInt LastIndexOf(char ch) const { - for (int i = length - 1; i >= 0; i--) - if (buffer[i] == ch) - return i; - return -1; + for (UInt i = getLength(); i > 0; i--) + if (getData()[i-1] == ch) + return i-1; + return UInt(-1); } bool StartsWith(const char * str) const // String str { if (!buffer) return false; - int strLen = (int)strlen(str); - if (strLen > length) + UInt strLen = strlen(str); + if (strLen > getLength()) return false; - for (int i = 0; i < strLen; i++) - if (str[i] != buffer[i]) + for (UInt i = 0; i < strLen; i++) + if (str[i] != getData()[i]) return false; return true; } bool StartsWith(const String & str) const { - return StartsWith(str.buffer.Ptr()); + return StartsWith(str.begin()); } - bool EndsWith(char * str) const // String str + bool EndsWith(char const * str) const // String str { if (!buffer) return false; - int strLen = (int)strlen(str); - if (strLen > length) + UInt strLen = strlen(str); + if (strLen > getLength()) return false; - for (int i = strLen - 1; i >= 0; i--) - if (str[i] != buffer[length - strLen + i]) + for (UInt i = strLen; i > 0; i--) + if (str[i-1] != getData()[getLength() - strLen + i-1]) return false; return true; } bool EndsWith(const String & str) const { - return EndsWith(str.buffer.Ptr()); + return EndsWith(str.begin()); } bool Contains(const char * str) const // String str @@ -508,52 +624,27 @@ namespace Slang bool Contains(const String & str) const { - return Contains(str.buffer.Ptr()); + return Contains(str.begin()); } int GetHashCode() const { - return Slang::GetHashCode((const char*)buffer.Ptr()); + return Slang::GetHashCode((const char*)begin()); } - String PadLeft(char ch, int length); - String PadRight(char ch, int length); - String ReplaceAll(String src, String dst) const; }; - class StringBuilder + class StringBuilder : public String { private: - char * buffer; - int length; - int bufferSize; - static const int InitialSize = 512; + static const int InitialSize = 1024; public: - StringBuilder(int bufferSize = 1024) - :buffer(0), length(0), bufferSize(0) - { - buffer = new char[InitialSize]; // new a larger buffer - buffer[0] = '\0'; - length = 0; - bufferSize = InitialSize; - } - ~StringBuilder() + explicit StringBuilder(int bufferSize = InitialSize) { - if (buffer) - delete[] buffer; + ensureUniqueStorageWithCapacity(bufferSize); } void EnsureCapacity(int size) { - if (bufferSize < size) - { - char * newBuffer = new char[size + 1]; - if (buffer) - { - strcpy_s(newBuffer, size + 1, buffer); - delete[] buffer; - } - buffer = newBuffer; - bufferSize = size; - } + ensureUniqueStorageWithCapacity(size); } StringBuilder & operator << (char ch) { @@ -649,31 +740,10 @@ namespace Slang } void Append(const char * str, int strLen) { - int newLength = length + strLen; - if (bufferSize < newLength + 1) - { - int newBufferSize = InitialSize; - while (newBufferSize < newLength + 1) - newBufferSize <<= 1; - char * newBuffer = new char[newBufferSize]; - if (buffer) - { - memcpy(newBuffer, buffer, length); - delete[] buffer; - } - memcpy(newBuffer + length, str, strLen); - newBuffer[newLength] = '\0'; - buffer = newBuffer; - bufferSize = newBufferSize; - } - else - { - memcpy(buffer + length, str, strLen); - buffer[newLength] = '\0'; - } - length = newLength; + append(str, str + strLen); } +#if 0 int Capacity() { return bufferSize; @@ -688,24 +758,19 @@ namespace Slang { return length; } +#endif String ToString() { - return String(buffer); + return *this; } String ProduceString() { - String rs; - rs.buffer = buffer; - rs.length = length; - buffer = 0; - bufferSize = 0; - length = 0; - return rs; - + return *this; } +#if 0 String GetSubString(int start, int count) { String rs; @@ -715,7 +780,9 @@ namespace Slang rs.buffer[count] = 0; return rs; } +#endif +#if 0 void Remove(int id, int len) { #if _DEBUG @@ -729,12 +796,11 @@ namespace Slang buffer[i - actualDelLength] = buffer[i]; length -= actualDelLength; } +#endif void Clear() { - length = 0; - if (buffer) - buffer[0] = 0; + buffer = 0; } }; diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h index d307e4e13..c31cdefe0 100644 --- a/source/core/smart-pointer.h +++ b/source/core/smart-pointer.h @@ -3,462 +3,191 @@ #include "type-traits.h" +#include <assert.h> + namespace Slang { - class RefPtrDefaultDestructor - { - public: - template<typename T> - void operator ()(T * ptr) - { - delete ptr; - } - }; - - class RefPtrArrayDestructor - { - public: - template<typename T> - void operator() (T * ptr) - { - delete [] ptr; - } - }; + // TODO: Need to centralize these typedefs + typedef uintptr_t UInt; + + // Base class for all reference-counted objects + class RefObject + { + private: + UInt referenceCount; + + public: + RefObject() + : referenceCount(0) + {} + + RefObject(const RefObject &) + : referenceCount(0) + {} + + virtual ~RefObject() + {} + + void addReference() + { + referenceCount++; + } + + void releaseReference() + { + assert(referenceCount != 0); + if(--referenceCount == 0) + { + delete this; + } + } + + bool isUniquelyReferenced() + { + assert(referenceCount != 0); + return referenceCount == 1; + } + }; + + inline void addReference(RefObject* obj) + { + if(obj) obj->addReference(); + } + + inline void releaseReference(RefObject* obj) + { + if(obj) obj->releaseReference(); + } + + // "Smart" pointer to a reference-counted object + template<typename T> + struct RefPtr + { + RefPtr() + : pointer(0) + {} + + RefPtr(T* p) + : pointer(p) + { + addReference(p); + } + + RefPtr(RefPtr<T> const& p) + : pointer(p.pointer) + { + addReference(p.pointer); + } + + RefPtr(RefPtr<T>&& p) + : pointer(p.pointer) + { + p.pointer = 0; + } + + template <typename U> + RefPtr(RefPtr<U> const& p, + typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0) + : pointer((U*) p) + { + addReference((U*) p); + } + +#if 0 + void operator=(T* p) + { + T* old = pointer; + addReference(p); + pointer = p; + releaseReference(old); + } +#endif + + void operator=(RefPtr<T> const& p) + { + T* old = pointer; + addReference(p.pointer); + pointer = p.pointer; + releaseReference(old); + } + + void operator=(RefPtr<T>&& p) + { + T* old = pointer; + pointer = p.pointer; + p.pointer = old; + } + + template <typename U> + typename EnableIf<IsConvertible<T*, U*>::value, void>::type + operator=(RefPtr<U> const& ptr) + { + T* old = pointer; + addReference(p.pointer); + pointer = p.pointer; + releaseReference(old); + } - class ReferenceCounted - { - template<typename T, bool b, typename Destructor> - friend class RefPtrImpl; - private: - int _refCount = 0; - public: - ReferenceCounted() {} - ReferenceCounted(const ReferenceCounted &) + int GetHashCode() { - _refCount = 0; + return (int)(long long)(void*)pointer; } - }; - - class RefObject : public ReferenceCounted - { - public: - virtual ~RefObject() - {} - }; + bool operator==(const T * ptr) const + { + return pointer == ptr; + } - template<typename T, bool HasBuiltInCounter, typename Destructor> - class RefPtrImpl - { - }; + bool operator!=(const T * ptr) const + { + return pointer != ptr; + } - template<typename T, typename Destructor = RefPtrDefaultDestructor> - using RefPtr = RefPtrImpl<T, IsBaseOf<ReferenceCounted, T>::Value, Destructor>; - - template<typename T, typename Destructor> - class RefPtrImpl<T, 0, Destructor> - { - template<typename T1, bool b, typename Destructor1> - friend class RefPtrImpl; - private: - T * pointer; - int * refCount; - - public: - RefPtrImpl() - { - pointer = 0; - refCount = 0; - } - RefPtrImpl(T * ptr) - : pointer(0), refCount(0) + bool operator==(RefPtr<T> const& ptr) const { - this->operator=(ptr); - } - RefPtrImpl(const RefPtrImpl<T, 0, Destructor> & ptr) - : pointer(0), refCount(0) - { - this->operator=(ptr); - } - RefPtrImpl(RefPtrImpl<T, 0, Destructor> && str) - : pointer(0), refCount(0) - { - this->operator=(static_cast<RefPtrImpl<T, 0, Destructor> &&>(str)); + return pointer == ptr.pointer; } - template <typename U> - RefPtrImpl(const RefPtrImpl<U, 0, Destructor>& ptr, - typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0) - : pointer(0), refCount(0) + bool operator!=(RefPtr<T> const& ptr) const { - pointer = ptr.pointer; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; + return pointer != ptr.pointer; } - template <typename U> - typename EnableIf<IsConvertible<T*, U*>::value, RefPtrImpl<T, 0, Destructor>>::type& - operator=(const RefPtrImpl<U,0,Destructor> & ptr) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; - return *this; - } + template<typename U> + RefPtr<U> As() const + { + RefPtr<U> result(dynamic_cast<U*>(pointer)); + return result; + } - RefPtrImpl<T, 0, Destructor>& operator=(const RefPtrImpl<T, 0, Destructor> & ptr) - { - Unreference(); - pointer = ptr.pointer; - if (ptr) - { - refCount = ptr.refCount; - (*refCount)++; - } - else - refCount = 0; - return *this; - } + ~RefPtr() + { + releaseReference(pointer); + } - RefPtrImpl<T, 0, Destructor>& operator=(T * ptr) - { - if (ptr != pointer) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - refCount = new int; - (*refCount) = 1; - } - else - refCount = 0; - } - return *this; - } - int GetHashCode() - { - return (int)(long long)(void*)pointer; - } - bool operator == (const T * ptr) const - { - return pointer == ptr; - } - bool operator != (const T * ptr) const - { - return pointer != ptr; - } - template<typename U> - bool operator == (const RefPtr<U, Destructor> & ptr) const - { - return pointer == ptr.pointer; - } - template<typename U> - bool operator != (const RefPtr<U, Destructor> & ptr) const - { - return pointer != ptr.pointer; - } - template<typename U> - RefPtrImpl<U, 0, Destructor> As() const - { - RefPtrImpl<U, 0, Destructor> result; - if (pointer) - { - result.pointer = dynamic_cast<U*>(pointer); - if (result.pointer) - { - result.refCount = refCount; - (*refCount)++; - } - } - return result; - } + T& operator*() const + { + return *pointer; + } - T* operator +(int offset) const - { - return pointer+offset; - } - T& operator [](int idx) const - { - return *(pointer + idx); - } - RefPtrImpl<T, 0, Destructor>& operator=(RefPtrImpl<T, 0, Destructor> && ptr) - { - if(ptr.pointer != pointer) - { - Unreference(); - pointer = ptr.pointer; - refCount = ptr.refCount; - ptr.pointer = 0; - ptr.refCount = 0; - } - return *this; - } - T* Release() - { - if(pointer) - { - if((*refCount) > 1) - { - (*refCount)--; - } - else - { - delete refCount; - } - } - auto rs = pointer; - refCount = 0; - pointer = 0; - return rs; - } - ~RefPtrImpl() - { - Unreference(); - } + T* operator->() const + { + return pointer; + } - void Unreference() - { - if(pointer) - { - if((*refCount) > 1) - { - (*refCount)--; - } - else - { - Destructor destructor; - destructor(pointer); - delete refCount; - } - } - } - T & operator *() const - { - return *pointer; - } - T * operator->() const - { - return pointer; - } T * Ptr() const { return pointer; } - public: - explicit operator bool() const - { - if (pointer) - return true; - else - return false; - } - }; - - - template<typename T, typename Destructor> - class RefPtrImpl<T, 1, Destructor> - { - template<typename T1, bool b, typename Destructor1> - friend class RefPtrImpl; - - private: - T * pointer; - public: - RefPtrImpl() - { - pointer = 0; - } - RefPtrImpl(T * ptr) - : pointer(0) - { - this->operator=(ptr); - } - RefPtrImpl(const RefPtrImpl<T, 1, Destructor> & ptr) - : pointer(0) - { - this->operator=(ptr); - } - RefPtrImpl(RefPtrImpl<T, 1, Destructor> && str) - : pointer(0) - { - this->operator=(static_cast<RefPtrImpl<T, 1, Destructor> &&>(str)); - } - template <typename U> - RefPtrImpl(const RefPtrImpl<U, 1, Destructor>& ptr, - typename EnableIf<IsConvertible<T*, U*>::Value, void>::type * = 0) - : pointer(0) - { - pointer = ptr.pointer; - if (ptr) - { - ptr->_refCount++; - } - } - template <typename U> - typename EnableIf<IsConvertible<T*, U*>::value, RefPtrImpl<T, 1, Destructor>&>::type - operator=(const RefPtrImpl<U, 1, Destructor> & ptr) - { - Unreference(); - - pointer = ptr.pointer; - if (ptr) - { - ptr->_refCount++; - } - return *this; - } - RefPtrImpl<T, 1, Destructor>& operator=(T * ptr) - { - if (ptr != pointer) - { - Unreference(); - - pointer = ptr; - if (ptr) - { - ptr->_refCount++; - } - } - return *this; - } - RefPtrImpl<T, 1, Destructor>& operator=(const RefPtrImpl<T, 1, Destructor> & ptr) - { - // Note: It is possible that the object this pointer references owns - // (directly or indirectly) the storage for the argument `ptr`. If - // that is the case and the `Unreference()` call below frees this - // object, then the argument would become invalid. - // - // We copy the pointer value out of the argument first, in order - // to protected against this case. - T* ptrPointer = ptr.pointer; - if (ptrPointer != pointer) - { - if (ptrPointer) - ptrPointer->_refCount++; - Unreference(); - pointer = ptrPointer; - } - return *this; - } - int GetHashCode() - { - return (int)(long long)(void*)pointer; - } - bool operator == (const T * ptr) const - { - return pointer == ptr; - } - bool operator != (const T * ptr) const - { - return pointer != ptr; - } - template<typename U> - bool operator == (const RefPtr<U, Destructor> & ptr) const - { - return pointer == ptr.pointer; - } - template<typename U> - bool operator != (const RefPtr<U, Destructor> & ptr) const - { - return pointer != ptr.pointer; - } - template<typename U> - RefPtrImpl<U, 1, Destructor> As() const - { - RefPtrImpl<U, 1, Destructor> result; - if (pointer) - { - result.pointer = dynamic_cast<U*>(pointer); - if (result.pointer) - { - result.pointer->_refCount++; - } - } - return result; - } - T* operator +(int offset) const - { - return pointer + offset; - } - T& operator [](int idx) const - { - return *(pointer + idx); - } - RefPtrImpl<T, 1, Destructor>& operator=(RefPtrImpl<T, 1, Destructor> && ptr) - { - if (ptr.pointer != pointer) - { - Unreference(); - pointer = ptr.pointer; - ptr.pointer = nullptr; - } - return *this; - } - T* Release() - { - if (pointer) - { - pointer->_refCount--; - } - auto rs = pointer; - pointer = 0; - return rs; - } - ~RefPtrImpl() - { - Unreference(); - } + operator T*() const + { + return pointer; + } - void Unreference() - { - if (pointer) - { - if (pointer->_refCount > 1) - { - pointer->_refCount--; - } - else - { - Destructor destructor; - destructor(pointer); - } - } - } - T & operator *() const - { - return *pointer; - } - T * operator->() const - { - return pointer; - } - T * Ptr() const - { - return pointer; - } - public: - explicit operator bool() const - { - if (pointer) - return true; - else - return false; - } + private: + T* pointer; + }; } diff --git a/source/core/stream.h b/source/core/stream.h index 0f5991cb7..9a8ea8366 100644 --- a/source/core/stream.h +++ b/source/core/stream.h @@ -32,7 +32,7 @@ namespace Slang Start, End, Current }; - class Stream + class Stream : public RefObject { public: virtual ~Stream() {} diff --git a/source/core/text-io.cpp b/source/core/text-io.cpp index 3e5013cf3..7815d7422 100644 --- a/source/core/text-io.cpp +++ b/source/core/text-io.cpp @@ -28,7 +28,7 @@ namespace Slang public: virtual void GetBytes(List<char> & result, const String & str) override { - int ptr = 0; + UInt ptr = 0; while (ptr < str.Length()) { int codePoint = GetUnicodePointFromUTF8([&](int) @@ -66,7 +66,7 @@ namespace Slang {} virtual void GetBytes(List<char> & result, const String & str) override { - int ptr = 0; + UInt ptr = 0; while (ptr < str.Length()) { int codePoint = GetUnicodePointFromUTF8([&](int) @@ -156,7 +156,7 @@ namespace Slang #else newLine = "\n"; #endif - for (int i = 0; i < str.Length(); i++) + for (UInt i = 0; i < str.Length(); i++) { if (str[i] == '\r') sb << newLine; diff --git a/source/core/text-io.h b/source/core/text-io.h index acdaf0b9d..9519d51f1 100644 --- a/source/core/text-io.h +++ b/source/core/text-io.h @@ -263,7 +263,7 @@ namespace Slang } void ReleaseStream() { - stream.Release(); + stream = 0; } }; @@ -308,7 +308,7 @@ namespace Slang } void ReleaseStream() { - stream.Release(); + stream = 0; } }; } diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 1424f6728..4966b102f 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -155,7 +155,7 @@ namespace Slang auto derefExpr = new DerefExpr(); derefExpr->Position = originalExpr->Position; derefExpr->base = base; - derefExpr->Type = ptrLikeType->elementType; + derefExpr->Type = QualType(ptrLikeType->elementType); // TODO(tfoley): handle l-value status here @@ -198,7 +198,7 @@ namespace Slang { auto overloadedExpr = new OverloadedExpr(); overloadedExpr->Position = originalExpr->Position; - overloadedExpr->Type = ExpressionType::Overloaded; + overloadedExpr->Type = QualType(ExpressionType::Overloaded); overloadedExpr->base = baseExpr; overloadedExpr->lookupResult2 = lookupResult; return overloadedExpr; @@ -236,7 +236,7 @@ namespace Slang } // TODO(tfoley): should we construct a new ErrorExpr here? - overloadedExpr->Type = ExpressionType::Error; + overloadedExpr->Type = QualType(ExpressionType::Error); return overloadedExpr; } @@ -518,7 +518,7 @@ namespace Slang RefPtr<ExpressionSyntaxNode> CreateErrorExpr(ExpressionSyntaxNode* expr) { - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); return expr; } @@ -787,7 +787,7 @@ namespace Slang { auto toInitializerListExpr = new InitializerListExpr(); toInitializerListExpr->Position = fromInitializerListExpr->Position; - toInitializerListExpr->Type = toType; + toInitializerListExpr->Type = QualType(toType); toInitializerListExpr->args = coercedArgs; @@ -960,7 +960,7 @@ namespace Slang auto castExpr = new TypeCastExpressionSyntaxNode(); castExpr->Position = fromExpr->Position; castExpr->TargetType.type = toType; - castExpr->Type = toType; + castExpr->Type = QualType(toType); castExpr->Expression = fromExpr; return castExpr; } @@ -1020,7 +1020,7 @@ namespace Slang // then coerce any initializer to the type if (initExpr) { - initExpr = Coerce(type, initExpr); + initExpr = Coerce(type.Ptr(), initExpr); } } else @@ -1668,7 +1668,7 @@ namespace Slang { if (function) { - stmt->Expression = Coerce(function->ReturnType, stmt->Expression); + stmt->Expression = Coerce(function->ReturnType.Ptr(), stmt->Expression); } else { @@ -1801,7 +1801,7 @@ namespace Slang // TODO(tfoley): should coercion of initializer lists be special-cased // here, or handled as a general case for coercion? - initExpr = Coerce(varDecl->Type, initExpr); + initExpr = Coerce(varDecl->Type.Ptr(), initExpr); varDecl->Expr = initExpr; } @@ -1903,7 +1903,7 @@ namespace Slang expr->Type = ExpressionType::GetFloat(); break; default: - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); throw "Invalid constant type."; break; } @@ -2167,7 +2167,7 @@ namespace Slang return CreateErrorExpr(subscriptExpr.Ptr()); } - subscriptExpr->Type = elementType; + subscriptExpr->Type = QualType(elementType); // TODO(tfoley): need to be more careful about this stuff subscriptExpr->Type.IsLeftValue = baseExpr->Type.IsLeftValue; @@ -2237,7 +2237,7 @@ namespace Slang auto elementType = CoerceToUsableType(TypeExp(baseExpr, baseTypeType->type)); auto arrayType = new ArrayExpressionType(); - arrayType->BaseType = elementType; + arrayType->BaseType = elementType.Ptr(); arrayType->ArrayLength = elementCount; typeResult = arrayType; @@ -2401,7 +2401,7 @@ namespace Slang { // TODO(tfoley): Actual checking logic needs to go here... - appExpr->Type = type; + appExpr->Type = QualType(type); return appExpr; } @@ -3290,7 +3290,7 @@ namespace Slang } context.mode = OverloadResolveContext::Mode::ForReal; - context.appExpr->Type = ExpressionType::Error; + context.appExpr->Type = QualType(ExpressionType::Error); if (!TryCheckOverloadCandidateArity(context, candidate)) goto error; @@ -3312,7 +3312,7 @@ namespace Slang { case OverloadCandidate::Flavor::Func: context.appExpr->FunctionExpr = baseExpr; - context.appExpr->Type = candidate.resultType; + context.appExpr->Type = QualType(candidate.resultType); // A call may yield an l-value, and we should take a look at the candidate to be sure if(auto subscriptDeclRef = candidate.item.declRef.As<SubscriptDecl>()) @@ -3771,7 +3771,7 @@ namespace Slang { ConstraintSystem constraints; - if (!TryUnifyTypes(constraints, extDecl->targetType, type)) + if (!TryUnifyTypes(constraints, extDecl->targetType.Ptr(), type)) return DeclRef<Decl>().As<ExtensionDecl>(); auto constraintSubst = TrySolveConstraintSystem(&constraints, DeclRef<Decl>(extGenericDecl, nullptr).As<GenericDecl>()); @@ -4291,7 +4291,7 @@ namespace Slang { // Nothing at all was found that we could even consider invoking getSink()->diagnose(expr->FunctionExpr, Diagnostics::expectedFunction); - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); return expr; } } @@ -4562,7 +4562,7 @@ namespace Slang if (expr->declRef) return expr; - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); auto lookupResult = LookUp(this, expr->name, expr->scope); if (lookupResult.isValid()) @@ -4587,7 +4587,7 @@ namespace Slang if (expr->Expression->Type->Equals(ExpressionType::Error.Ptr())) { // If the expression being casted has an error type, then just silently succeed - expr->Type = targetType; + expr->Type = targetType.Ptr(); return expr; } else if (auto targetArithType = targetType->AsArithmeticType()) @@ -4604,7 +4604,7 @@ namespace Slang // TODO(tfoley): this checking is incomplete here, and could // lead to downstream compilation failures - expr->Type = targetType; + expr->Type = targetType.Ptr(); return expr; } } @@ -4612,7 +4612,7 @@ namespace Slang fail: // Default: in no other case succeds, then the cast failed and we emit a diagnostic. getSink()->diagnose(expr, Diagnostics::invalidTypeCast, expr->Expression->Type, targetType->ToString()); - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); return expr; } #if TIMREMOVED @@ -4656,11 +4656,11 @@ namespace Slang auto& type = expr->Type; if (auto pointerLikeType = type->As<PointerLikeType>()) { - type = pointerLikeType->elementType; + type = QualType(pointerLikeType->elementType); auto derefExpr = new DerefExpr(); derefExpr->base = expr; - derefExpr->Type = pointerLikeType->elementType; + derefExpr->Type = QualType(pointerLikeType->elementType); // TODO(tfoley): deal with l-value-ness here @@ -4691,7 +4691,7 @@ namespace Slang bool anyDuplicates = false; bool anyError = false; - for (int i = 0; i < memberRefExpr->name.Length(); i++) + for (UInt i = 0; i < memberRefExpr->name.Length(); i++) { auto ch = memberRefExpr->name[i]; int elementIndex = -1; @@ -4738,7 +4738,7 @@ namespace Slang if (anyError) { - swizExpr->Type = ExpressionType::Error; + swizExpr->Type = QualType(ExpressionType::Error); } else if (elementCount == 1) { @@ -4747,15 +4747,15 @@ namespace Slang // Note(tfoley): the official HLSL rules seem to be that it produces // a one-component vector, which is then implicitly convertible to // a scalar, but that seems like it just adds complexity. - swizExpr->Type = baseElementType; + swizExpr->Type = QualType(baseElementType); } else { // TODO(tfoley): would be nice to "re-sugar" type // here if the input type had a sugared name... - swizExpr->Type = createVectorType( + swizExpr->Type = QualType(createVectorType( baseElementType, - new ConstantIntVal(elementCount)); + new ConstantIntVal(elementCount))); } // A swizzle can be used as an l-value as long as there @@ -4861,14 +4861,14 @@ namespace Slang // catch-all fail: getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); return expr; } // All remaining cases assume we have a `BasicType` else if (!baseType->AsBasicType()) - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); else - expr->Type = ExpressionType::Error; + expr->Type = QualType(ExpressionType::Error); if (!baseType->Equals(ExpressionType::Error.Ptr()) && expr->Type->Equals(ExpressionType::Error.Ptr())) { @@ -5023,7 +5023,7 @@ namespace Slang { sink->diagnose(declRef, Diagnostics::unimplemented, "cannot form reference to this kind of declaration"); } - return ExpressionType::Error; + return QualType(ExpressionType::Error); } QualType getTypeForDeclRef( diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp index 786376baf..2d75e1900 100644 --- a/source/slang/lexer.cpp +++ b/source/slang/lexer.cpp @@ -415,7 +415,7 @@ namespace Slang return tokenType; } - static bool isNumberExponent(char c, int base) + static bool isNumberExponent(int c, int base) { switch( c ) { @@ -497,7 +497,6 @@ namespace Slang for(;;) { - int digitVal = 0; int c = *cursor; switch(c) { diff --git a/source/slang/options.cpp b/source/slang/options.cpp index 62b45e025..cced0f0ff 100644 --- a/source/slang/options.cpp +++ b/source/slang/options.cpp @@ -238,7 +238,7 @@ struct OptionsParser } else { - fprintf(stderr, "unknown code generation target '%S'\n", name.ToWString()); + fprintf(stderr, "unknown code generation target '%S'\n", name.ToWString().begin()); exit(1); } @@ -302,7 +302,7 @@ struct OptionsParser else if (name == "glslang") { passThrough = SLANG_PASS_THROUGH_GLSLANG; } else { - fprintf(stderr, "unknown pass-through target '%S'\n", name.ToWString()); + fprintf(stderr, "unknown pass-through target '%S'\n", name.ToWString().begin()); exit(1); } @@ -387,7 +387,7 @@ struct OptionsParser } else { - fprintf(stderr, "unknown command-line option '%S'\n", argStr.ToWString()); + fprintf(stderr, "unknown command-line option '%S'\n", argStr.ToWString().begin()); // TODO: print a usage message exit(1); } diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index 01b047c2c..2a0c64892 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -211,8 +211,8 @@ LayoutSemanticInfo ExtractLayoutSemanticInfo( // TODO: need to parse and handle `space` binding int space = 0; - int index = 0; - for (int ii = 1; ii < registerName.Length(); ++ii) + UInt index = 0; + for (UInt ii = 1; ii < registerName.Length(); ++ii) { int c = registerName[ii]; if (c >= '0' && c <= '9') diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index cd839415f..4f622ada6 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -3277,7 +3277,7 @@ namespace Slang constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Int; constExpr->integerValue = value; - constExpr->Type = suffixType; + constExpr->Type = QualType(suffixType); return constExpr; } @@ -3346,7 +3346,7 @@ namespace Slang constExpr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Float; constExpr->floatingPointValue = value; - constExpr->Type = suffixType; + constExpr->Type = QualType(suffixType); return constExpr; } diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index 7643b3b85..b43387ddd 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -1975,7 +1975,7 @@ sb << TEXT; void SlangStdLib::Finalize() { - code = nullptr; + code = String(); stdlibPath = String(); glslLibraryCode = String(); } diff --git a/source/slang/syntax.h b/source/slang/syntax.h index 05d3b6a79..b4d7e146e 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -664,26 +664,11 @@ namespace Slang : IsLeftValue(false) {} - QualType(RefPtr<ExpressionType> type) - : type(type) - , IsLeftValue(false) - {} - QualType(ExpressionType* type) : type(type) , IsLeftValue(false) {} - void operator=(RefPtr<ExpressionType> t) - { - *this = QualType(t); - } - - void operator=(ExpressionType* t) - { - *this = QualType(t); - } - ExpressionType* Ptr() { return type.Ptr(); } operator RefPtr<ExpressionType>() { return type; } @@ -1444,7 +1429,7 @@ namespace Slang return type->Equals(other.Ptr()); } ExpressionType* Ptr() { return type.Ptr(); } - operator RefPtr<ExpressionType>() + operator ExpressionType*() { return type; } @@ -1473,7 +1458,7 @@ namespace Slang inline RefPtr<ExpressionType> GetType(DeclRef<VarDeclBase> const& declRef) { - return declRef.Substitute(declRef.getDecl()->Type); + return declRef.Substitute(declRef.getDecl()->Type.Ptr()); } inline RefPtr<ExpressionSyntaxNode> getInitExpr(DeclRef<VarDeclBase> const& declRef) @@ -1519,7 +1504,7 @@ namespace Slang inline RefPtr<ExpressionType> GetTargetType(DeclRef<ExtensionDecl> const& declRef) { - return declRef.Substitute(declRef.getDecl()->targetType); + return declRef.Substitute(declRef.getDecl()->targetType.Ptr()); } // Declaration of a type that represents some sort of aggregate @@ -1620,7 +1605,7 @@ namespace Slang inline RefPtr<ExpressionType> GetType(DeclRef<TypeDefDecl> const& declRef) { - return declRef.Substitute(declRef.getDecl()->Type); + return declRef.Substitute(declRef.getDecl()->Type.Ptr()); } // A type alias of some kind (e.g., via `typedef`) @@ -2423,12 +2408,12 @@ namespace Slang inline RefPtr<ExpressionType> GetSub(DeclRef<GenericTypeConstraintDecl> const& declRef) { - return declRef.Substitute(declRef.getDecl()->sub); + return declRef.Substitute(declRef.getDecl()->sub.Ptr()); } inline RefPtr<ExpressionType> GetSup(DeclRef<GenericTypeConstraintDecl> const& declRef) { - return declRef.Substitute(declRef.getDecl()->sup); + return declRef.Substitute(declRef.getDecl()->sup.Ptr()); } class GenericValueParamDecl : public VarDeclBase @@ -2482,7 +2467,7 @@ namespace Slang // - class SyntaxVisitor + class SyntaxVisitor : public RefObject { protected: DiagnosticSink * sink = nullptr; diff --git a/source/slangc/main.cpp b/source/slangc/main.cpp index 4a783a17c..a643e26eb 100644 --- a/source/slangc/main.cpp +++ b/source/slangc/main.cpp @@ -84,7 +84,7 @@ int MAIN(int argc, char** argv) #ifndef _DEBUG catch (Exception & e) { - printf("internal compiler error: %S\n", e.Message.ToWString()); + printf("internal compiler error: %S\n", e.Message.ToWString().begin()); return 1; } #endif diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp index 7a0cac3ce..2bca2f78d 100644 --- a/tools/slang-test/main.cpp +++ b/tools/slang-test/main.cpp @@ -548,7 +548,7 @@ OSError spawnAndWait(String testPath, OSProcessSpawner& spawner) { if( options.shouldBeVerbose ) { - fprintf(stderr, "%s\n", spawner.commandLine_.Buffer()); + fprintf(stderr, "%s\n", spawner.commandLine_.ToString().begin()); } OSError err = spawner.spawnAndWaitForCompletion(); @@ -1149,7 +1149,7 @@ void handleTestResult( break; } - printf("%s test: '%S'\n", resultString, testName.ToWString()); + printf("%s test: '%S'\n", resultString, testName.ToWString().begin()); } break; diff --git a/tools/slang-test/os.cpp b/tools/slang-test/os.cpp index 63db4f9ad..40fd8afff 100644 --- a/tools/slang-test/os.cpp +++ b/tools/slang-test/os.cpp @@ -314,8 +314,8 @@ OSError OSProcessSpawner::spawnAndWaitForCompletion() // `CreateProcess` requires write access to this, for some reason... BOOL success = CreateProcessW( - isExecutablePath_ ? executableName_.ToWString() : nullptr, - (LPWSTR)commandLine_.ToString().ToWString(), + isExecutablePath_ ? executableName_.ToWString().begin() : nullptr, + (LPWSTR)commandLine_.ToString().ToWString().begin(), nullptr, nullptr, true, |
