+2001-09-19 Miguel de Icaza <miguel@ximian.com>
+
+ * typemanager.cs (TypeManager::CoreLookupType): A function to make sure that we
+ are loading the correct data types (throws an exception if not).
+ (TypeManager::InitCoreTypes): Use CoreLookupType
+
+ * expression.cs (Unary::ResolveOperator): return the child
+ expression for expressions which are just +expr.
+ (Unary::ResolveOperator): Return negative literals for -LITERAL
+ expressions (otherwise they are Unary {Literal}).
+ (Invocation::Badness): Take into account `Implicit constant
+ expression conversions'.
+
+ * literal.cs (LongLiteral): Implement long literal class.
+ (IntLiteral): export the `Value' of the intliteral.
+
2001-09-19 Ravi Pratap <ravi@ximian.com>
* expression.cs (Binary::Emit): Finally get the emission right ! Woo!
methods = new ArrayList ();
methods.Add (method);
- DefineName (name, method);
+ if (value != null)
+ DefineName (name, method);
return AdditionResult.Success;
}
AppDomain current_domain;
AssemblyBuilder assembly_builder;
ModuleBuilder module_builder;
+
+ string Basename (string name)
+ {
+ int pos = name.LastIndexOf ("/");
+
+ if (pos != -1)
+ return name.Substring (pos + 1);
+
+ pos = name.LastIndexOf ("\\");
+ if (pos != -1)
+ return name.Substring (pos + 1);
+
+ return name;
+ }
public CodeGen (string name, string output)
{
an.Name = "AssemblyName";
current_domain = AppDomain.CurrentDomain;
assembly_builder = current_domain.DefineDynamicAssembly (
- an, AssemblyBuilderAccess.RunAndSave);
-
- module_builder = assembly_builder.DefineDynamicModule (name, output);
+ an, AssemblyBuilderAccess.RunAndSave);
+
+ //
+ // Pass a path-less name to DefineDynamicModule. Wonder how
+ // this copes with output in different directories then.
+ // FIXME: figure out how this copes with --output /tmp/blah
+ //
+ module_builder = assembly_builder.DefineDynamicModule (
+ Basename (name), Basename (output));
}
public AssemblyBuilder AssemblyBuilder {
public void Save (Report report, string name)
{
+ Console.WriteLine ("This is it " + Basename (name));
+
try {
- assembly_builder.Save (name);
+ assembly_builder.Save (Basename (name));
} catch (System.IO.IOException io){
report.Error (16, "Coult not write to file `"+name+"', cause: " + io.Message);
}
if (e == null)
return false;
-
+
if (e.Type != TypeManager.bool_type)
e = Expression.ConvertImplicit (e, TypeManager.bool_type);
Statement false_stat = s.FalseStatement;
bool is_ret;
- Console.WriteLine ("Emitting IF");
-
if (!EmitBoolExpression (s.Expr))
return false;
- Console.WriteLine ("Ok, so like the bool expression was emitted");
ig.Emit (OpCodes.Brfalse, false_target);
is_ret = EmitStatement (s.TrueStatement);
/>\r
<Reference\r
Name = "System.XML"\r
- AssemblyName = "System.XML"\r
+ AssemblyName = "System.Xml"\r
/>\r
</References>\r
</Build>\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "cil-codegen.cs"\r
+ RelPath = "attribute.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "codegen.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "constant.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "driver.cs"\r
+ RelPath = "delegate.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "enum.cs"\r
+ RelPath = "driver.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "errors.cs"\r
+ RelPath = "enum.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
+ <File\r
+ RelPath = "genericparser.cs"\r
+ SubType = "Code"\r
+ BuildAction = "Compile"\r
+ />\r
<File\r
RelPath = "gen-treedump.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "tree.cs"\r
+ RelPath = "support.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
<File\r
- RelPath = "type.cs"\r
+ RelPath = "tree.cs"\r
SubType = "Code"\r
BuildAction = "Compile"\r
/>\r
EnableUnmanagedDebugging = "false"\r
EnableSQLServerDebugging = "false"\r
StartAction = "Project"\r
- StartArguments = "i-undefined.cs"\r
+ StartArguments = "c:\mono\mcs\test\test-4.cs"\r
StartPage = ""\r
StartProgram = ""\r
StartURL = ""\r
Location l = lexer.Location;\r
rc.Report.Error (1, l, "THIS IS CRAZY");\r
}\r
- $$ = new Invocation ((Expression) $1, (ArrayList) $3);\r
+ $$ = new Invocation ((Expression) $1, (ArrayList) $3, lexer.Location);\r
+ \r
}\r
; \r
\r
foreach_block.AddVariable ((string) $3, (string) $4);\r
assign_e = new Assign (new LocalVariableReference (foreach_block, temp_id), \r
new Invocation (\r
- new MemberAccess ((Expression) $6, "GetEnumerator"), null));\r
+ new MemberAccess ((Expression) $6, "GetEnumerator"), \r
+ null, lexer.Location));\r
current_block.AddStatement (new StatementExpression (assign_e));\r
ma = new MemberAccess (new LocalVariableReference (foreach_block, temp_id), "MoveNext");\r
child_block = new Block (current_block);\r
{\r
string s = number.ToString ();\r
\r
- Console.WriteLine (s);\r
switch (t){\r
case Token.LITERAL_DECIMAL:\r
val = new System.Decimal ();\r
}
}
+ //
+ // A plus in front of something is just a no-op
+ //
+ if (oper == Operator.Add)
+ return expr;
+
+ //
+ // Fold -Constant into a negative constant
+ //make
+ if (oper == Operator.Subtract){
+ Expression e = null;
+
+ if (expr is IntLiteral)
+ e = new IntLiteral (-((IntLiteral) expr).Value);
+ else if (expr is LongLiteral)
+ e = new LongLiteral (-((LongLiteral) expr).Value);
+ else if (expr is FloatLiteral)
+ e = new FloatLiteral (-((FloatLiteral) expr).Value);
+
+ if (e != null){
+ e = e.Resolve (tc);
+ return e;
+ }
+ }
+
// FIXME : Are we supposed to check that we have an object type
// for & and * operators ?
switch (oper){
case Operator.Add:
- // Which one ?
- break;
+ throw new Exception ("This should be caught by Resolve");
case Operator.Subtract:
// Which one ?
public override Expression Resolve (TypeContainer tc)
{
// FIXME: Implement;
+ throw new Exception ("Unimplemented");
return this;
}
public override Expression Resolve (TypeContainer tc)
{
- // FIXME: Implement;
+ type = tc.LookupType (target_type, false);
+ eclass = ExprClass.Value;
+
+ if (type == null)
+ return null;
+
+ // FIXME: Finish this.
return this;
}
public override Expression Resolve (TypeContainer tc)
{
// FIXME: Implement;
+ throw new Exception ("Unimplemented");
+
return this;
}
VariableInfo vi = VariableInfo;
ILGenerator ig = ec.ig;
int idx = vi.Idx;
-
+
+ Console.WriteLine ("Variable: " + vi);
switch (idx){
case 0:
ig.Emit (OpCodes.Ldloc_0);
// </summary>
public class Invocation : Expression {
public readonly ArrayList Arguments;
+ public readonly Location Location;
+
Expression expr;
MethodBase method = null;
-
+
static Hashtable method_parameter_cache;
static Invocation ()
// FIXME: only allow expr to be a method invocation or a
// delegate invocation (7.5.5)
//
- public Invocation (Expression expr, ArrayList arguments)
+ public Invocation (Expression expr, ArrayList arguments, Location l)
{
this.expr = expr;
Arguments = arguments;
+ Location = l;
}
public Expression Expr {
}
/// <summary>
- /// Computes whether Argument `a' and the ParameterInfo `pi' are
+ /// Computes whether Argument `a' and the Type t of the ParameterInfo `pi' are
/// compatible, and if so, how good is the match (in terms of
/// "better conversions" (7.4.2.3).
///
/// </summary>
static int Badness (Argument a, Type t)
{
- if (a.Expr.Type == null){
+ Expression argument_expr = a.Expr;
+ Type argument_type = argument_expr.Type;
+
+ if (argument_type == null){
throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
}
- if (t == a.Expr.Type)
+ if (t == argument_type)
return 0;
+
+ //
+ // Now probe whether an implicit constant expression conversion
+ // can be used.
+ //
+ // An implicit constant expression conversion permits the following
+ // conversions:
+ //
+ // * A constant-expression of type `int' can be converted to type
+ // sbyte, byute, short, ushort, uint, ulong provided the value of
+ // of the expression is withing the range of the destination type.
+ //
+ // * A constant-expression of type long can be converted to type
+ // ulong, provided the value of the constant expression is not negative
+ //
+ // FIXME: Note that this assumes that constant folding has
+ // taken place. We dont do constant folding yet.
+ //
+
+ if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
+ IntLiteral ei = (IntLiteral) argument_expr;
+ int value = ei.Value;
+
+ if (t == TypeManager.sbyte_type){
+ if (value >= SByte.MinValue && value <= SByte.MaxValue)
+ return 1;
+ } else if (t == TypeManager.byte_type){
+ if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
+ return 1;
+ } else if (t == TypeManager.short_type){
+ if (value >= Int16.MinValue && value <= Int16.MaxValue)
+ return 1;
+ } else if (t == TypeManager.ushort_type){
+ if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
+ return 1;
+ } else if (t == TypeManager.uint32_type){
+ //
+ // we can optimize this case: a positive int32
+ // always fits on a uint32
+ //
+ if (value >= 0)
+ return 1;
+ } else if (t == TypeManager.uint64_type){
+ //
+ // we can optimize this case: a positive int32
+ // always fits on a uint64
+ //
+ if (value >= 0)
+ return 1;
+ }
+ } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
+ LongLiteral ll = (LongLiteral) argument_expr;
+
+ if (t == TypeManager.uint64_type){
+ if (ll.Value > 0)
+ return 1;
+ }
+ }
- // FIXME: Implement implicit conversions here.
+ // FIXME: Implement user-defined implicit conversions here.
// FIXME: Implement better conversion here.
return -1;
Argument a = (Argument) Arguments [j];
x = Badness (a, pd.ParameterType (j));
-
+
if (x < 0){
badness = best_match;
continue;
method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
if (method == null){
- tc.RootContext.Report.Error (-6,
+ tc.RootContext.Report.Error (-6, Location,
"Figure out error: Can not find a good function for this argument list");
return null;
}
public override Expression Resolve (TypeContainer tc)
{
// FIXME: Implement;
+ throw new Exception ("Unimplemented");
+
return this;
}
public override Expression Resolve (TypeContainer tc)
{
// FIXME: Implement;
+ throw new Exception ("Unimplemented");
+
return this;
}
override public void Emit (EmitContext ec)
{
- // FIXME: Implement.
+ // FIXME: Implement;
+ throw new Exception ("Unimplemented");
}
}
public override Expression Resolve (TypeContainer tc)
{
- // FIXME : Implement
+ // FIXME: Implement;
+ throw new Exception ("Unimplemented");
+
return this;
}
public override Expression Resolve (TypeContainer tc)
{
- // FIXME : Implement !
+ // FIXME: Implement;
+ throw new Exception ("Unimplemented");
+
return this;
}
}
return c.ToString ();
}
+
+ protected Literal ()
+ {
+ eclass = ExprClass.Value;
+ }
}
public class NullLiteral : Literal {
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.object_type;
-
return this;
}
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.bool_type;
return this;
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.char_type;
return this;
}
public class IntLiteral : Literal {
- int i;
+ public readonly int Value;
public IntLiteral (int l)
{
- i = l;
+ Value = l;
}
override public string AsString ()
{
- return i.ToString ();
+ return Value.ToString ();
}
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.int32_type;
return this;
{
ILGenerator ig = ec.ig;
- EmitInt (ig, i);
+ EmitInt (ig, Value);
}
static public void EmitInt (ILGenerator ig, int i)
}
}
+ public class LongLiteral : Literal {
+ public readonly long Value;
+
+ public LongLiteral (long l)
+ {
+ Value = l;
+ }
+
+ override public string AsString ()
+ {
+ return Value.ToString ();
+ }
+
+ public override Expression Resolve (TypeContainer tc)
+ {
+ type = TypeManager.int64_type;
+
+ return this;
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ EmitLong (ig, Value);
+ }
+
+ static public void EmitLong (ILGenerator ig, long l)
+ {
+ if (l >= -1 || l < Int32.MaxValue)
+ IntLiteral.EmitInt (ig, (int) l);
+ else
+ ig.Emit (OpCodes.Ldc_I8, l);
+ }
+ }
+
public class FloatLiteral : Literal {
- float f;
+ public readonly float Value;
public FloatLiteral (float f)
{
- this.f = f;
+ Value = f;
}
override public string AsString ()
{
- return f.ToString ();
+ return Value.ToString ();
}
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.float_type;
return this;
public override void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldc_R4, f);
+ ec.ig.Emit (OpCodes.Ldc_R4, Value);
}
}
public class DoubleLiteral : Literal {
- double d;
+ public readonly double Value;
public DoubleLiteral (double d)
{
- this.d = d;
+ Value = d;
}
override public string AsString ()
{
- return d.ToString ();
+ return Value.ToString ();
}
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.double_type;
return this;
public override void Emit (EmitContext ec)
{
- ec.ig.Emit (OpCodes.Ldc_R8, d);
+ ec.ig.Emit (OpCodes.Ldc_R8, Value);
}
}
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.decimal_type;
return this;
public override Expression Resolve (TypeContainer tc)
{
- eclass = ExprClass.Value;
type = TypeManager.string_type;
return this;
t = (Type) types [name];
if (t != null)
return t;
-
+
foreach (Assembly a in assemblies){
t = a.GetType (name);
if (t != null){
else
return t.FullName;
}
-
+
+ Type CoreLookupType (string name)
+ {
+ Type t = LookupType (name);
+
+ if (t == null)
+ throw new Exception ("Can not find core type " + name);
+
+ return t;
+ }
+
// <remarks>
// The types have to be initialized after the initial
// population of the type has happened (for example, to
// </remarks>
public void InitCoreTypes ()
{
- object_type = LookupType ("System.Object");
- string_type = LookupType ("System.String");
- int32_type = LookupType ("System.Int32");
- int64_type = LookupType ("System.Int64");
- uint32_type = LookupType ("System.UInt32");
- uint64_type = LookupType ("System.UInt64");
- float_type = LookupType ("System.Single");
- double_type = LookupType ("System.Double");
- byte_type = LookupType ("System.Byte");
- sbyte_type = LookupType ("System.SByte");
- char_type = LookupType ("System.Char");
- short_type = LookupType ("System.Short");
- decimal_type = LookupType ("System.Decimal");
- bool_type = LookupType ("System.Bool");
+ object_type = CoreLookupType ("System.Object");
+ string_type = CoreLookupType ("System.String");
+ int32_type = CoreLookupType ("System.Int32");
+ int64_type = CoreLookupType ("System.Int64");
+ uint32_type = CoreLookupType ("System.UInt32");
+ uint64_type = CoreLookupType ("System.UInt64");
+ float_type = CoreLookupType ("System.Single");
+ double_type = CoreLookupType ("System.Double");
+ byte_type = CoreLookupType ("System.Byte");
+ sbyte_type = CoreLookupType ("System.SByte");
+ char_type = CoreLookupType ("System.Char");
+ short_type = CoreLookupType ("System.Int16");
+ ushort_type = CoreLookupType ("System.UInt16");
+ decimal_type = CoreLookupType ("System.Decimal");
+ bool_type = CoreLookupType ("System.Boolean");
}
public MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf, MemberFilter filter, object criteria)
--- /dev/null
+TEST_SOURCES = \
+ test-1 test-2 test-3
+
+test-compiler:
+ for i in $(TEST_SOURCES); do \
+ if ../mcs/compiler $$i.cs > /dev/null; then \
+ if ./$$i.exe; then \
+ echo $$i: ok; \
+ else \
+ echo failed; \
+ fi; \
+ else \
+ echo compiler failed on $$i; \
+ fi \
+ done
--- /dev/null
+using System;
+
+class X {
+ static int Main (string [] args)
+ {
+ Console.WriteLine ("Hello, World!");
+ return 0;
+ }
+}
--- /dev/null
+class X {
+ static int Main (string [] args)
+ {
+ System.Console.WriteLine ("Hello, World");
+ }
+}
--- /dev/null
+
+public class TestIntOps {
+
+ public static sbyte sbyte_add (sbyte a, sbyte b) {
+ return (sbyte)(a+b);
+ }
+
+ public static short short_add (short a, short b) {
+ return (short)(a+b);
+ }
+
+ public static double double_add (double a, double b) {
+ return a+b;
+ }
+
+ public static int int_add (int a, int b) {
+ return a+b;
+ }
+
+ public static int int_sub (int a, int b) {
+ return a-b;
+ }
+
+ public static int int_mul (int a, int b) {
+ return a*b;
+ }
+
+ public static int Main() {
+ int num = 1;
+
+ if (int_add (1, 1) != 2) return num;
+ num++;
+
+ if (int_add (31, -1) != 30) return num;
+ num++;
+
+ if (int_sub (31, -1) != 32) return num;
+ num++;
+
+ if (int_mul (12, 12) != 144) return num;
+ num++;
+
+ if (sbyte_add (1, 1) != 2) return num;
+ num++;
+
+ if (sbyte_add (31, -1) != 30) return num;
+ num++;
+
+ if (short_add (1, 1) != 2) return num;
+ num++;
+
+ if (short_add (31, -1) != 30) return num;
+ num++;
+
+ if (double_add (1.5, 1.5) != 3) return num;
+ num++;
+
+ // add more meaningful tests
+
+ return 0;
+ }
+}
--- /dev/null
+using System;
+class X {
+ bool sbyte_selected;
+ bool int_selected;
+
+ void test (sbyte s)
+ {
+ sbyte_selected = true;
+ }
+
+ void test (int i)
+ {
+ int_selected = true;
+ }
+
+ static int Main ()
+ {
+ X x = new X ();
+
+ x.test (1);
+ if (x.sbyte_selected){
+ Console.WriteLine ("FAILED: Sbyte selected on constant int argument");
+ return 1;
+ } else {
+ Console.WriteLine ("OK: int selected for constant constant int");
+ }
+
+ X y = new X ();
+ sbyte s = 10;
+
+ y.test (s);
+ if (y.sbyte_selected){
+ Console.WriteLine ("OK: sbyte selected for sbyte argument");
+ } else {
+ Console.WriteLine ("FAILED: sbyte not selected for sbyte argument");
+ return 1;
+ }
+ return 0;
+ }
+}
--- /dev/null
+using System;
+class X {
+ bool sbyte_selected;
+ bool int_selected;
+
+ void test (sbyte s)
+ {
+ sbyte_selected = true;
+ }
+
+ void test (int i)
+ {
+ int_selected = true;
+ }
+
+ static int Main ()
+ {
+ X y = new X ();
+ sbyte s = 10;
+
+ y.test (s);
+ if (y.sbyte_selected){
+ Console.WriteLine ("OK: sbyte selected for sbyte argument");
+ } else {
+ Console.WriteLine ("FAILED: sbyte not selected for sbyte argument");
+ return 1;
+ }
+ return 0;
+ }
+}