Mercurial > projects > ddmd
comparison dmd/FuncDeclaration.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | 1765f3ef917d |
children | 206db751bd4c |
comparison
equal
deleted
inserted
replaced
129:010eb8f0e18d | 130:60bb0fe4563e |
---|---|
52 import dmd.InvariantDeclaration; | 52 import dmd.InvariantDeclaration; |
53 import dmd.TY; | 53 import dmd.TY; |
54 import dmd.PtrExp; | 54 import dmd.PtrExp; |
55 import dmd.DeclarationExp; | 55 import dmd.DeclarationExp; |
56 import dmd.InlineDoState; | 56 import dmd.InlineDoState; |
57 import dmd.Argument; | 57 import dmd.Parameter; |
58 import dmd.StructDeclaration; | 58 import dmd.StructDeclaration; |
59 import dmd.ClassDeclaration; | 59 import dmd.ClassDeclaration; |
60 import dmd.InterfaceDeclaration; | 60 import dmd.InterfaceDeclaration; |
61 import dmd.Array; | 61 import dmd.Array; |
62 import dmd.Statement; | 62 import dmd.Statement; |
71 import dmd.Type; | 71 import dmd.Type; |
72 import dmd.BUILTIN; | 72 import dmd.BUILTIN; |
73 import dmd.TypeFunction; | 73 import dmd.TypeFunction; |
74 import dmd.Expression; | 74 import dmd.Expression; |
75 import dmd.STC; | 75 import dmd.STC; |
76 import dmd.TRUST; | |
76 import dmd.Dsymbol; | 77 import dmd.Dsymbol; |
77 import dmd.Scope; | 78 import dmd.Scope; |
78 import dmd.OutBuffer; | 79 import dmd.OutBuffer; |
79 import dmd.HdrGenState; | 80 import dmd.HdrGenState; |
80 import dmd.MATCH; | 81 import dmd.MATCH; |
306 | 307 |
307 if (!originalType) | 308 if (!originalType) |
308 originalType = type; | 309 originalType = type; |
309 if (!type.deco) | 310 if (!type.deco) |
310 { | 311 { |
311 /* Apply const and invariant storage class | 312 /* Apply const, immutable and shared storage class |
312 * to the function type | 313 * to the function type |
313 */ | 314 */ |
314 type = type.semantic(loc, sc); | 315 type = type.semantic(loc, sc); |
315 STC stc = storage_class; | 316 STC stc = storage_class; |
316 if (type.isInvariant()) | 317 if (type.isInvariant()) |
358 { | 359 { |
359 error("%s must be a function", toChars()); | 360 error("%s must be a function", toChars()); |
360 return; | 361 return; |
361 } | 362 } |
362 f = cast(TypeFunction)type; | 363 f = cast(TypeFunction)type; |
363 size_t nparams = Argument.dim(f.parameters); | 364 size_t nparams = Parameter.dim(f.parameters); |
364 | 365 |
365 linkage = sc.linkage; | 366 linkage = sc.linkage; |
366 // if (!parent) | 367 // if (!parent) |
367 { | 368 { |
368 //parent = sc.scopesym; | 369 //parent = sc.scopesym; |
731 case 0: | 732 case 0: |
732 break; | 733 break; |
733 | 734 |
734 case 1: | 735 case 1: |
735 { | 736 { |
736 Argument arg0 = Argument.getNth(f.parameters, 0); | 737 auto arg0 = Parameter.getNth(f.parameters, 0); |
737 if (arg0.type.ty != TY.Tarray || | 738 if (arg0.type.ty != TY.Tarray || |
738 arg0.type.nextOf().ty != TY.Tarray || | 739 arg0.type.nextOf().ty != TY.Tarray || |
739 arg0.type.nextOf().nextOf().ty != TY.Tchar || | 740 arg0.type.nextOf().nextOf().ty != TY.Tchar || |
740 arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) | 741 arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) |
741 goto Lmainerr; | 742 goto Lmainerr; |
765 { if (f.varargs == 1) | 766 { if (f.varargs == 1) |
766 goto Lassignerr; | 767 goto Lassignerr; |
767 } | 768 } |
768 else | 769 else |
769 { | 770 { |
770 Argument arg0 = Argument.getNth(f.parameters, 0); | 771 auto arg0 = Parameter.getNth(f.parameters, 0); |
771 Type t0 = arg0.type.toBasetype(); | 772 Type t0 = arg0.type.toBasetype(); |
772 Type tb = sd ? sd.type : cd.type; | 773 Type tb = sd ? sd.type : cd.type; |
773 if (arg0.type.implicitConvTo(tb) || | 774 if (arg0.type.implicitConvTo(tb) || |
774 (sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb)) | 775 (sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb)) |
775 ) | 776 ) |
776 { | 777 { |
777 if (nparams == 1) | 778 if (nparams == 1) |
778 goto Lassignerr; | 779 goto Lassignerr; |
779 Argument arg1 = Argument.getNth(f.parameters, 1); | 780 auto arg1 = Parameter.getNth(f.parameters, 1); |
780 if (arg1.defaultArg) | 781 if (arg1.defaultArg) |
781 goto Lassignerr; | 782 goto Lassignerr; |
782 } | 783 } |
783 } | 784 } |
784 } | 785 } |
815 */ | 816 */ |
816 if (!outId && f.nextOf().toBasetype().ty != Tvoid) | 817 if (!outId && f.nextOf().toBasetype().ty != Tvoid) |
817 outId = Id.result; // provide a default | 818 outId = Id.result; // provide a default |
818 | 819 |
819 Loc loc = fensure.loc; | 820 Loc loc = fensure.loc; |
820 Arguments arguments = new Arguments(); | 821 auto arguments = new Parameters(); |
821 Argument a = null; | 822 Parameter a = null; |
822 if (outId) | 823 if (outId) |
823 { | 824 { |
824 a = new Argument(STCref, f.nextOf(), outId, null); | 825 a = new Parameter(STCref, f.nextOf(), outId, null); |
825 arguments.push(a); | 826 arguments.push(a); |
826 } | 827 } |
827 TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd); | 828 TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd); |
828 FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf); | 829 FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf); |
829 fd.fbody = fensure; | 830 fd.fbody = fensure; |
921 sc2.sbreak = null; | 922 sc2.sbreak = null; |
922 sc2.scontinue = null; | 923 sc2.scontinue = null; |
923 sc2.sw = null; | 924 sc2.sw = null; |
924 sc2.fes = fes; | 925 sc2.fes = fes; |
925 sc2.linkage = LINK.LINKd; | 926 sc2.linkage = LINK.LINKd; |
926 sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref); | 927 sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | |
927 sc2.protection = PROT.PROTpublic; | 928 STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref | |
929 STCproperty | STCsafe | STCtrusted | STCsystem); | |
930 sc2.protection = PROT.PROTpublic; | |
928 sc2.explicitProtection = 0; | 931 sc2.explicitProtection = 0; |
929 sc2.structalign = 8; | 932 sc2.structalign = 8; |
930 sc2.incontract = 0; | 933 sc2.incontract = 0; |
931 sc2.tf = null; | 934 sc2.tf = null; |
932 sc2.noctor = 0; | 935 sc2.noctor = 0; |
1058 foreach (arg; f.parameters) | 1061 foreach (arg; f.parameters) |
1059 { | 1062 { |
1060 //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars()); | 1063 //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars()); |
1061 if (arg.type.ty == TY.Ttuple) | 1064 if (arg.type.ty == TY.Ttuple) |
1062 { auto t = cast(TypeTuple)arg.type; | 1065 { auto t = cast(TypeTuple)arg.type; |
1063 size_t dim = Argument.dim(t.arguments); | 1066 size_t dim = Parameter.dim(t.arguments); |
1064 for (size_t j = 0; j < dim; j++) | 1067 for (size_t j = 0; j < dim; j++) |
1065 { Argument narg = Argument.getNth(t.arguments, j); | 1068 { |
1066 narg.storageClass = arg.storageClass; | 1069 auto narg = Parameter.getNth(t.arguments, j); |
1070 narg.storageClass = arg.storageClass; | |
1067 } | 1071 } |
1068 } | 1072 } |
1069 } | 1073 } |
1070 } | 1074 } |
1071 | 1075 |
1072 /* Declare all the function parameters as variables | 1076 /* Declare all the function parameters as variables |
1073 * and install them in parameters[] | 1077 * and install them in parameters[] |
1074 */ | 1078 */ |
1075 size_t nparams = Argument.dim(f.parameters); | 1079 size_t nparams = Parameter.dim(f.parameters); |
1076 if (nparams) | 1080 if (nparams) |
1077 { /* parameters[] has all the tuples removed, as the back end | 1081 { /* parameters[] has all the tuples removed, as the back end |
1078 * doesn't know about tuples | 1082 * doesn't know about tuples |
1079 */ | 1083 */ |
1080 parameters = new Dsymbols(); | 1084 parameters = new Dsymbols(); |
1081 parameters.reserve(nparams); | 1085 parameters.reserve(nparams); |
1082 for (size_t i = 0; i < nparams; i++) | 1086 for (size_t i = 0; i < nparams; i++) |
1083 { | 1087 { |
1084 Argument arg = Argument.getNth(f.parameters, i); | 1088 auto arg = Parameter.getNth(f.parameters, i); |
1085 Identifier id = arg.ident; | 1089 Identifier id = arg.ident; |
1086 if (!id) | 1090 if (!id) |
1087 { | 1091 { |
1088 /* Generate identifier for un-named parameter, | 1092 /* Generate identifier for un-named parameter, |
1089 * because we need it later on. | 1093 * because we need it later on. |
1117 { | 1121 { |
1118 if (!arg.ident) | 1122 if (!arg.ident) |
1119 continue; // never used, so ignore | 1123 continue; // never used, so ignore |
1120 if (arg.type.ty == TY.Ttuple) | 1124 if (arg.type.ty == TY.Ttuple) |
1121 { auto t = cast(TypeTuple)arg.type; | 1125 { auto t = cast(TypeTuple)arg.type; |
1122 size_t dim = Argument.dim(t.arguments); | 1126 size_t dim = Parameter.dim(t.arguments); |
1123 Objects exps = new Objects(); | 1127 Objects exps = new Objects(); |
1124 exps.setDim(dim); | 1128 exps.setDim(dim); |
1125 for (size_t j = 0; j < dim; j++) | 1129 for (size_t j = 0; j < dim; j++) |
1126 { Argument narg = Argument.getNth(t.arguments, j); | 1130 { auto narg = Parameter.getNth(t.arguments, j); |
1127 assert(narg.ident); | 1131 assert(narg.ident); |
1128 VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration(); | 1132 VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration(); |
1129 assert(v); | 1133 assert(v); |
1130 Expression e = new VarExp(v.loc, v); | 1134 Expression e = new VarExp(v.loc, v); |
1131 exps[j] = e; | 1135 exps[j] = e; |
1188 outId = Id.result; // provide a default | 1192 outId = Id.result; // provide a default |
1189 } | 1193 } |
1190 | 1194 |
1191 if (outId) | 1195 if (outId) |
1192 { // Declare result variable | 1196 { // Declare result variable |
1193 VarDeclaration v; | |
1194 Loc loc = this.loc; | 1197 Loc loc = this.loc; |
1195 | 1198 |
1196 if (fensure) | 1199 if (fensure) |
1197 loc = fensure.loc; | 1200 loc = fensure.loc; |
1198 | 1201 |
1199 v = new VarDeclaration(loc, type.nextOf(), outId, null); | 1202 auto v = new VarDeclaration(loc, type.nextOf(), outId, null); |
1200 v.noauto = true; | 1203 v.noauto = true; |
1201 version (DMDV2) { | 1204 version (DMDV2) { |
1205 if (!isVirtual()) | |
1206 v.storage_class |= STC.STCconst; | |
1202 if (f.isref) | 1207 if (f.isref) |
1203 { | 1208 { |
1204 v.storage_class |= STC.STCref | STC.STCforeach; | 1209 v.storage_class |= STC.STCref | STC.STCforeach; |
1205 } | 1210 } |
1206 } | 1211 } |
1895 scope OutBuffer buf2 = new OutBuffer(); | 1900 scope OutBuffer buf2 = new OutBuffer(); |
1896 tf.modToBuffer(buf2); | 1901 tf.modToBuffer(buf2); |
1897 | 1902 |
1898 //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco); | 1903 //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco); |
1899 error(loc, "%s%s is not callable using argument types %s", | 1904 error(loc, "%s%s is not callable using argument types %s", |
1900 Argument.argsTypesToChars(tf.parameters, tf.varargs), | 1905 Parameter.argsTypesToChars(tf.parameters, tf.varargs), |
1901 buf2.toChars(), | 1906 buf2.toChars(), |
1902 buf.toChars()); | 1907 buf.toChars()); |
1903 return m.anyf; // as long as it's not a FuncAliasDeclaration | 1908 return m.anyf; // as long as it's not a FuncAliasDeclaration |
1904 } | 1909 } |
1905 else | 1910 else |
1908 TypeFunction t1 = cast(TypeFunction)m.lastf.type; | 1913 TypeFunction t1 = cast(TypeFunction)m.lastf.type; |
1909 TypeFunction t2 = cast(TypeFunction)m.nextf.type; | 1914 TypeFunction t2 = cast(TypeFunction)m.nextf.type; |
1910 | 1915 |
1911 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", | 1916 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", |
1912 buf.toChars(), | 1917 buf.toChars(), |
1913 m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs), | 1918 m.lastf.toPrettyChars(), Parameter.argsTypesToChars(t1.parameters, t1.varargs), |
1914 m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs)); | 1919 m.nextf.toPrettyChars(), Parameter.argsTypesToChars(t2.parameters, t2.varargs)); |
1915 } else { | 1920 } else { |
1916 error(loc, "overloads %s and %s both match argument list for %s", | 1921 error(loc, "overloads %s and %s both match argument list for %s", |
1917 m.lastf.type.toChars(), | 1922 m.lastf.type.toChars(), |
1918 m.nextf.type.toChars(), | 1923 m.nextf.type.toChars(), |
1919 m.lastf.toChars()); | 1924 m.lastf.toChars()); |
1941 * as g() is. | 1946 * as g() is. |
1942 */ | 1947 */ |
1943 | 1948 |
1944 TypeFunction tf = cast(TypeFunction)type; | 1949 TypeFunction tf = cast(TypeFunction)type; |
1945 TypeFunction tg = cast(TypeFunction)g.type; | 1950 TypeFunction tg = cast(TypeFunction)g.type; |
1946 size_t nfparams = Argument.dim(tf.parameters); | 1951 size_t nfparams = Parameter.dim(tf.parameters); |
1947 size_t ngparams = Argument.dim(tg.parameters); | 1952 size_t ngparams = Parameter.dim(tg.parameters); |
1948 MATCH match = MATCHexact; | 1953 MATCH match = MATCHexact; |
1949 | 1954 |
1950 /* If both functions have a 'this' pointer, and the mods are not | 1955 /* If both functions have a 'this' pointer, and the mods are not |
1951 * the same and g's is not const, then this is less specialized. | 1956 * the same and g's is not const, then this is less specialized. |
1952 */ | 1957 */ |
1965 */ | 1970 */ |
1966 scope Expressions args = new Expressions(); | 1971 scope Expressions args = new Expressions(); |
1967 args.setDim(nfparams); | 1972 args.setDim(nfparams); |
1968 for (int u = 0; u < nfparams; u++) | 1973 for (int u = 0; u < nfparams; u++) |
1969 { | 1974 { |
1970 Argument p = Argument.getNth(tf.parameters, u); | 1975 auto p = Parameter.getNth(tf.parameters, u); |
1971 Expression e; | 1976 Expression e; |
1972 if (p.storageClass & (STCref | STCout)) | 1977 if (p.storageClass & (STCref | STCout)) |
1973 { | 1978 { |
1974 e = new IdentifierExp(Loc(0), p.ident); | 1979 e = new IdentifierExp(Loc(0), p.ident); |
1975 e.type = p.type; | 1980 e.type = p.type; |
2250 //printf("FuncDeclaration::isPure() '%s'\n", toChars()); | 2255 //printf("FuncDeclaration::isPure() '%s'\n", toChars()); |
2251 assert(type.ty == TY.Tfunction); | 2256 assert(type.ty == TY.Tfunction); |
2252 return (cast(TypeFunction)this.type).ispure; | 2257 return (cast(TypeFunction)this.type).ispure; |
2253 } | 2258 } |
2254 | 2259 |
2260 int isSafe() | |
2261 { | |
2262 assert(type.ty == TY.Tfunction); | |
2263 return (cast(TypeFunction)this.type).trust == TRUST.TRUSTsafe; | |
2264 } | |
2265 | |
2266 int isTrusted() | |
2267 { | |
2268 assert(type.ty == TY.Tfunction); | |
2269 return (cast(TypeFunction)this.type).trust == TRUST.TRUSTtrusted; | |
2270 } | |
2271 | |
2255 bool isNested() | 2272 bool isNested() |
2256 { | 2273 { |
2257 //if (!toParent()) | 2274 //if (!toParent()) |
2258 //printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent); | 2275 //printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent); |
2259 //printf("\ttoParent2() = '%s'\n", toParent2().toChars()); | 2276 //printf("\ttoParent2() = '%s'\n", toParent2().toChars()); |
2390 } | 2407 } |
2391 | 2408 |
2392 // Ensure there are no lazy parameters | 2409 // Ensure there are no lazy parameters |
2393 if (tf.parameters) | 2410 if (tf.parameters) |
2394 { | 2411 { |
2395 size_t dim = Argument.dim(tf.parameters); | 2412 size_t dim = Parameter.dim(tf.parameters); |
2396 for (size_t i = 0; i < dim; i++) | 2413 for (size_t i = 0; i < dim; i++) |
2397 { | 2414 { |
2398 Argument arg = Argument.getNth(tf.parameters, i); | 2415 auto arg = Parameter.getNth(tf.parameters, i); |
2399 if (arg.storageClass & STClazy) | 2416 if (arg.storageClass & STClazy) |
2400 { | 2417 { |
2401 cantInterpret = 1; | 2418 cantInterpret = 1; |
2402 return null; | 2419 return null; |
2403 } | 2420 } |
2431 eargs.setDim(dim); | 2448 eargs.setDim(dim); |
2432 | 2449 |
2433 for (size_t i = 0; i < dim; i++) | 2450 for (size_t i = 0; i < dim; i++) |
2434 { | 2451 { |
2435 Expression earg = arguments[i]; | 2452 Expression earg = arguments[i]; |
2436 Argument arg = Argument.getNth(tf.parameters, i); | 2453 auto arg = Parameter.getNth(tf.parameters, i); |
2437 | 2454 |
2438 if (arg.storageClass & (STCout | STCref)) | 2455 if (arg.storageClass & (STCout | STCref)) |
2439 { | 2456 { |
2440 } | 2457 } |
2441 else | 2458 else |
2460 } | 2477 } |
2461 | 2478 |
2462 for (size_t i = 0; i < dim; i++) | 2479 for (size_t i = 0; i < dim; i++) |
2463 { | 2480 { |
2464 auto earg = eargs[i]; | 2481 auto earg = eargs[i]; |
2465 Argument arg = Argument.getNth(tf.parameters, i); | 2482 auto arg = Parameter.getNth(tf.parameters, i); |
2466 auto v = cast(VarDeclaration)parameters[i]; | 2483 auto v = cast(VarDeclaration)parameters[i]; |
2467 vsave[i] = v.value; | 2484 vsave[i] = v.value; |
2468 version (LOG) { | 2485 version (LOG) { |
2469 printf("arg[%d] = %s\n", i, earg.toChars()); | 2486 printf("arg[%d] = %s\n", i, earg.toChars()); |
2470 } | 2487 } |