Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/AST/build.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,8 @@ buildClassDefExpr(const char* name,
// possible in the compiler. gatherWellKnownTypes runs too late to be of use
// to us.
if (strcmp("string", name) == 0) {
// If we want to change dtString to refer to string(ascii),
// this might be the place to do it.
*dtString = *ct;
// These fields get overwritten with `ct` by the assignment. These fields are
// set to `this` by the AggregateType constructor so they should still be
Expand Down
8 changes: 8 additions & 0 deletions compiler/AST/symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ GenRet VarSymbol::codegen() {
if( outfile ) {
// dtString immediates don't actually codegen as immediates, we just use
// them for param string functionality.

// Consider changing this isStringType to support
// utf-8 and ascii string literals
if (immediate && ret.chplType != dtString) {
ret.isLVPtr = GEN_VAL;
if (immediate->const_kind == CONST_KIND_STRING) {
Expand Down Expand Up @@ -3160,6 +3163,9 @@ VarSymbol *new_StringSymbol(const char *str) {
gFalse); // owned = false
ctor->insertAtTail(gFalse); // needToCopy = false

// Either:
// change dtString to be concrete, or
// make this new VarSymbol have a concrete string(ascii) type
s = new VarSymbol(astr("_str_literal_", istr(literal_id++)), dtString);
s->addFlag(FLAG_NO_AUTO_DESTROY);
s->addFlag(FLAG_CONST);
Expand Down Expand Up @@ -3386,6 +3392,8 @@ static Type*
immediate_type(Immediate *imm) {
switch (imm->const_kind) {
case CONST_KIND_STRING: {
// We might need to have string_kind for UTF-8 and ASCII strings.
// (would need to change ifa/num.h and ifa/num.cpp)
if (imm->string_kind == STRING_KIND_STRING) {
return dtString;
} else if (imm->string_kind == STRING_KIND_C_STRING) {
Expand Down
3 changes: 3 additions & 0 deletions compiler/AST/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,9 @@ bool isArrayClass(Type* type) {
bool isString(Type* type) {
bool retval = false;

// Pretty sure this needs to return true if isStringType
// would return true

if (AggregateType* aggr = toAggregateType(type))
retval = strcmp(aggr->symbol->name, "string") == 0;

Expand Down
11 changes: 10 additions & 1 deletion compiler/include/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,12 @@ TYPE_EXTERN PrimitiveType* dtSyncVarAuxFields;
TYPE_EXTERN PrimitiveType* dtSingleVarAuxFields;

// Well-known types
TYPE_EXTERN AggregateType* dtString;
TYPE_EXTERN AggregateType* dtString; // consider renaming this dtStringGeneric

// Add:
// dtStringAscii
// dtStringUTF8

TYPE_EXTERN AggregateType* dtArray;
TYPE_EXTERN AggregateType* dtBaseArr;
TYPE_EXTERN AggregateType* dtBaseDom;
Expand Down Expand Up @@ -296,12 +301,16 @@ bool isDistImplType(Type* t);
bool isSyncType(Type* t);
bool isAtomicType(Type* t);
bool isRefIterType(Type* t);
// isStringType
// returns true for generic version, string(ascii), string(utf-8)
// ie all instantiations of the generic version

bool isSubClass(Type* type, Type* baseType);
bool isDistClass(Type* type);
bool isDomainClass(Type* type);
bool isArrayClass(Type* type);

// ? is same as isStringType?
bool isString(Type* type);
bool isUserDefinedRecord(Type* type);

Expand Down
2 changes: 2 additions & 0 deletions compiler/optimizations/bulkCopyRecords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ static bool isTrivialAssignment(FnSymbol* fn)
// Skip this optimization for string/wide string types
// (due to problems providing additional arguments for
// PRIM_ASSIGN).

// This needs to call isStringType or check for either UTF-8/ascii string
if (argType == dtString)
return false;

Expand Down
4 changes: 4 additions & 0 deletions compiler/passes/buildDefaultFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ static void build_enum_cast_function(EnumType* et) {
fn->addFlag(FLAG_COMPILER_GENERATED);
arg1 = new ArgSymbol(INTENT_BLANK, "t", dtAny);
arg1->addFlag(FLAG_TYPE_VARIABLE);
// This argument should be a generic string type
arg2 = new ArgSymbol(INTENT_BLANK, "_arg2", dtString);
fn->insertFormalAtTail(arg1);
fn->insertFormalAtTail(arg2);
Expand Down Expand Up @@ -1300,6 +1301,7 @@ static void buildDefaultReadWriteFunctions(AggregateType* ct) {


static void buildStringCastFunction(EnumType* et) {
// Think this one should be the generic string
if (function_exists("_cast", 2, dtString, et))
return;

Expand All @@ -1311,6 +1313,8 @@ static void buildStringCastFunction(EnumType* et) {
ArgSymbol* arg = new ArgSymbol(INTENT_BLANK, "this", et);
arg->addFlag(FLAG_ARG_THIS);
fn->insertFormalAtTail(arg);
// This one needs to turn into : string
// with the generic string type
fn->where = new BlockStmt(new CallExpr("==", t, dtString->symbol));

for_enums(constant, et) {
Expand Down
1 change: 1 addition & 0 deletions compiler/passes/checkResolved.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ static void checkExternProcs() {
continue;

for_formals(formal, fn) {
// This should call isStringType
if (formal->typeInfo() == dtString) {
if (fn->instantiatedFrom == NULL) {
USR_FATAL_CONT(fn, "extern procedures should not take arguments of "
Expand Down
2 changes: 2 additions & 0 deletions compiler/passes/filesToAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ static WellKnownType sWellKnownTypes[] = {
{"BaseDom", &dtBaseDom, true},
{"BaseDist", &dtDist, true},
{"chpl_main_argument", &dtMainArgument, false}
// Can dtStringAscii be added here to
// refer to a type asciiString = string(ascii) ?
};


Expand Down
1 change: 1 addition & 0 deletions compiler/passes/parallel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ static void findHeapVarsAndRefs(Map<Symbol*,Vec<SymExpr*>*>& defMap,
!isSyncType(def->sym->type) &&
// Dont try to broadcast string literals, they'll get fixed in
// another manner
// Should call isStringType
(def->sym->type != dtString)))) {
// replicate global const of primitive type
INT_ASSERT(defMap.get(def->sym) && defMap.get(def->sym)->n == 1);
Expand Down
54 changes: 54 additions & 0 deletions compiler/resolution/functionResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@ resolveFormals(FnSymbol* fn) {
continue;

// Don't pass dtString params in by reference
// Should call isStringType
if(formal->type == dtString && formal->hasFlag(FLAG_INSTANTIATED_PARAM))
continue;

Expand Down Expand Up @@ -1242,6 +1243,7 @@ canInstantiate(Type* actualType, Type* formalType) {
(is_int_type(actualType) || is_uint_type(actualType) || is_imag_type(actualType) ||
is_real_type(actualType) || is_complex_type(actualType)))
return true;
// use isStringType, including possibly a generic string
if (formalType == dtString && actualType==dtStringC)
return true;
if (formalType == dtStringC && actualType==dtStringCopy)
Expand Down Expand Up @@ -1325,6 +1327,8 @@ static bool canParamCoerce(Type* actualType, Symbol* actualSym, Type* formalType
if (fits_in_uint(get_width(formalType), var->immediate))
return true;
}

// isStringType(actualType)
if (formalType == dtStringC && actualType == dtString)
if (actualSym && actualSym->isImmediate())
return true;
Expand Down Expand Up @@ -1370,6 +1374,8 @@ canCoerce(Type* actualType, Symbol* actualSym, Type* formalType, FnSymbol* fn, b
}
if (actualType->symbol->hasFlag(FLAG_REF))
return canDispatch(actualType->getValType(), NULL, formalType, fn, promotes);

// isStringType(formalType)
if (formalType == dtString && actualType == dtStringCopy)
return true;
if (formalType == dtStringC && actualType == dtStringCopy)
Expand Down Expand Up @@ -1599,7 +1605,9 @@ computeGenericSubs(SymbolMap &subs,
// foo("bar");
// and pass "bar" as a c_string instead of a string
if (fn->hasFlag(FLAG_EXTERN) && (formal->type == dtAny) &&
// (type == dtString) -> isStringType(type)
(!formal->hasFlag(FLAG_PARAM)) && (type == dtString) &&
// isStringType(alignedA...)
(alignedActuals.v[i]->type == dtString) &&
(alignedActuals.v[i]->isImmediate())) {
subs.put(formal, dtStringC->symbol);
Expand Down Expand Up @@ -2214,6 +2222,8 @@ static bool paramWorks(Symbol* actual, Type* formalType) {
return fits_in_uint(get_width(formalType), imm);
}
if (imm->const_kind == CONST_KIND_STRING) {
// isStringType for now, but maybe put a comment
// that it it wouldn't work for UTF-16 e.g.
if (formalType == dtStringC && actual->type == dtString) {
return true;
}
Expand Down Expand Up @@ -5658,6 +5668,10 @@ preFold(Expr* expr) {
is_bool_type(oldType)) &&
(is_int_type(newType) || is_uint_type(newType) ||
is_bool_type(newType) || is_enum_type(newType) ||
// newType can be string(ascii) or string(utf8)
// couldn't be called with generic
// isStringType and maybe a comment about
// UTF-16 being disqualified
newType == dtString || newType == dtStringC)) {
VarSymbol* typevar = toVarSymbol(newType->defaultValue);
EnumType* typeenum = toEnumType(newType);
Expand All @@ -5669,9 +5683,12 @@ preFold(Expr* expr) {
coerce_immediate(var->immediate, &coerce);
result = new SymExpr(new_ImmediateSymbol(&coerce));
call->replace(result);
// isStringType
} else if (newType == dtString) {
// typevar will be null for dtString so we need a special
// case.

// newType -> STRING_KIND_STRING_UTF8/ASCII
Immediate coerce = Immediate("", STRING_KIND_STRING);
coerce_immediate(var->immediate, &coerce);
result = new SymExpr(new_StringSymbol(coerce.v_string));
Expand Down Expand Up @@ -5699,6 +5716,7 @@ preFold(Expr* expr) {
} else {
INT_FATAL("unexpected case in cast_fold");
}
// isStringType but not UTF-16
} else if (oldType == dtString && newType == dtStringC) {
result = new SymExpr(new_CStringSymbol(var->immediate->v_string));
call->replace(result);
Expand All @@ -5708,6 +5726,7 @@ preFold(Expr* expr) {
} else if (EnumSymbol* enumSym = toEnumSymbol(sym->var)) {
if (SymExpr* sym = toSymExpr(call->get(1))) {
Type* newType = sym->var->type;
// isStringType
if (newType == dtString) {
result = new SymExpr(new_StringSymbol(enumSym->name));
call->replace(result);
Expand Down Expand Up @@ -6583,6 +6602,8 @@ postFold(Expr* expr) {
if (lhs->var->isParameter() && rhs->var->isParameter()) {
const char* lstr = get_string(lhs);
const char* rstr = get_string(rhs);
// isStringType
// alternatively, could be !(dtStringC || dtStringCopy)
if (lhs->var->type == dtString)
result = new SymExpr(new_StringSymbol(astr(lstr, rstr)));
else
Expand Down Expand Up @@ -6935,6 +6956,8 @@ resolveExpr(Expr* expr) {
// Don't try to resolve the defaultTypeConstructor for string literals
// (resolution ordering issue, string literals are encountered too early
// on and we don't know enough to be able to resolve them at that point)

// isStringType, but won't be generic
if (!(ct == dtString && (sym->var->isParameter() ||
sym->var->hasFlag(FLAG_INSTANTIATED_PARAM))) &&
!ct->symbol->hasFlag(FLAG_GENERIC) &&
Expand Down Expand Up @@ -7823,6 +7846,37 @@ resolve() {

resolveExternVarSymbols();

// At least by here
// resolve string(ascii) and string(utf8) types
// set dtStringAscii and dtStringUTF8 to them


// 2 approaches:
// 1) resolve string(ascii) and string(utf8)
// by creating calls to their type constructor

/*
// ? is the type constructor really called string, or something else?

CallExpr* asciiEnum = new CallExpr("chpl_get_string_ascii_enum");


CallExpr* call = new CallExpr(dtString->defaultTypeConstructor
asciiEnum);

// insert it in the AST somewhere...
// Try putting it into the String module's init function?
resolveCallAndCallee(call);
*/

// 2) in String.chpl, make declarations like
// type asciiString = string(ascii);
// type utf8String = string(utf8);

// at this point, you'd have say
// make new SymExpr( "string_ascii" )
// dtStringAscii = resolveTypeAlias(se)

// --ipe does not build a mainModule
if (mainModule)
resolveUses(mainModule);
Expand Down
1 change: 1 addition & 0 deletions compiler/resolution/generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ renameInstantiatedType(TypeSymbol* sym, SymbolMap& subs, FnSymbol* fn) {
VarSymbol* var = toVarSymbol(value);
if (var && var->immediate) {
Immediate* immediate = var->immediate;
// should use isStringType
if (var->type == dtString || var->type == dtStringC)
renameInstantiatedTypeString(sym, var);
else if (immediate->const_kind == NUM_KIND_BOOL) {
Expand Down
1 change: 1 addition & 0 deletions compiler/resolution/wrappers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ void coerceActuals(FnSymbol* fn, CallInfo* info) {
c2 = false;
Type* actualType = actualSym->type;
if (needToAddCoercion(actualType, actualSym, formalType, fn)) {
// actualType == dtString -> isStringType(actualType)
if (formalType == dtStringC && actualType == dtString && actualSym->isImmediate()) {
// We do this swap since we know the string is a valid literal
// There also is no cast defined for string->c_string on purpose (you
Expand Down
6 changes: 6 additions & 0 deletions modules/internal/String.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,12 @@ module String {

} // end record string

// Part of one approach ?
// proc chpl_get_string_ascii_enum() {
// return Encoding.ascii;
// }
// type string_ascii = string(Encoding.ascii);
// type string_utf8 = string(Encoding.utf8);

// We'd like this to be by ref, but doing so leads to an internal
// compiler error. See
Expand Down