diff --git a/src/Draco.Compiler.Tests/EndToEnd/BclUsageTests.cs b/src/Draco.Compiler.Tests/EndToEnd/BclUsageTests.cs index 282961a83..3a5869f42 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/BclUsageTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/BclUsageTests.cs @@ -469,4 +469,32 @@ public void NumericsVectorNegationWithoutImportingNamespace() Assert.Equal(new Vector2(-1, -2), result); } + + [Fact] + public void AccessingConstants() + { + var assembly = Compile(""" + import System.Math; + + public func get_pi(): float64 = PI; + """); + + var result = Invoke(assembly: assembly, methodName: "get_pi"); + + Assert.Equal(Math.PI, result); + } + + [Fact] + public void ChainedValueTypeMemberAccess() + { + var assembly = Compile(""" + import System; + + public func get_datetime_str(): string = DateTime.Now.TimeOfDay.ToString(); + """); + + var result = Invoke(assembly: assembly, methodName: "get_datetime_str"); + + Assert.NotNull(result); + } } diff --git a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs index 127fc70a9..43960fe1d 100644 --- a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs @@ -476,9 +476,43 @@ private void EncodePush(IOperand operand) case Constant c: switch (c.Value) { + // Unsigned integers + case byte b: + this.InstructionEncoder.LoadConstantI4(b); + break; + case ushort s: + this.InstructionEncoder.LoadConstantI4(s); + break; + case uint i: + this.InstructionEncoder.LoadConstantI4(unchecked((int)i)); + break; + case ulong l: + this.InstructionEncoder.LoadConstantI8(unchecked((long)l)); + break; + + // Signed integers + case sbyte b: + this.InstructionEncoder.LoadConstantI4(b); + break; + case short s: + this.InstructionEncoder.LoadConstantI4(s); + break; case int i: this.InstructionEncoder.LoadConstantI4(i); break; + case long l: + this.InstructionEncoder.LoadConstantI8(l); + break; + + // Floating point + case float f: + this.InstructionEncoder.LoadConstantR4(f); + break; + case double d: + this.InstructionEncoder.LoadConstantR8(d); + break; + + // Others case bool b: this.InstructionEncoder.LoadConstantI4(b ? 1 : 0); break; @@ -489,6 +523,7 @@ private void EncodePush(IOperand operand) var stringHandle = this.GetStringLiteralHandle(s); this.InstructionEncoder.LoadString(stringHandle); break; + default: throw new NotImplementedException(); } diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataMethodSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataMethodSymbol.cs index 89d7e2c92..b4885d6fb 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataMethodSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataMethodSymbol.cs @@ -194,8 +194,8 @@ private void BuildOverride() var definition = this.MetadataReader.GetMethodDefinition(methodDef); var name = this.MetadataReader.GetString(definition.Name); var provider = this.Assembly.Compilation.TypeProvider; - var signature = definition.DecodeSignature(provider, this); var containingType = provider.GetTypeFromDefinition(this.MetadataReader, definition.GetDeclaringType(), 0); + var signature = definition.DecodeSignature(provider, containingType); return GetFunctionWithSignature(containingType, name, signature); } @@ -204,11 +204,23 @@ private void BuildOverride() var reference = this.MetadataReader.GetMemberReference(methodRef); var name = this.MetadataReader.GetString(reference.Name); var provider = this.Assembly.Compilation.TypeProvider; - var signature = reference.DecodeMethodSignature(provider, this); - var containingType = provider.GetTypeFromReference(this.MetadataReader, (TypeReferenceHandle)reference.Parent, 0); + var containingType = this.GetTypeFromHandle(reference.Parent); + var signature = reference.DecodeMethodSignature(provider, containingType); return GetFunctionWithSignature(containingType, name, signature); } + private TypeSymbol GetTypeFromHandle(EntityHandle handle) + { + var typeProvider = this.Assembly.Compilation.TypeProvider; + return handle.Kind switch + { + HandleKind.TypeDefinition => typeProvider.GetTypeFromDefinition(this.MetadataReader, (TypeDefinitionHandle)handle, 0), + HandleKind.TypeReference => typeProvider.GetTypeFromReference(this.MetadataReader, (TypeReferenceHandle)handle, 0), + HandleKind.TypeSpecification => typeProvider.GetTypeFromSpecification(this.MetadataReader, this, (TypeSpecificationHandle)handle, 0), + _ => throw new InvalidOperationException(), + }; + } + private static FunctionSymbol? GetFunctionWithSignature( TypeSymbol containingType, string name,