상속: CiSymbol
예제 #1
0
        void Write(CiClass klass, CiMethod method)
        {
            if (method.CallType == CiCallType.Abstract)
            {
                return;
            }
            WriteLine();
            WriteDoc(method);
            Write(klass.Name);
            Write('.');
            if (method.CallType != CiCallType.Static)
            {
                Write("prototype.");
            }
            WriteCamelCase(method.Name);
            Write(" = function(");
            bool first = true;

            foreach (CiVar param in method.Parameters)
            {
                if (!first)
                {
                    Write(", ");
                }
                first = false;
                Write(param.Name);
                if (param.Value != null)
                {
                    Write(" = ");
                    param.Value.Accept(this, CiPriority.Statement);
                }
            }
            Write(')');
            WriteBody(method);
        }
예제 #2
0
 static void MarkInternal(CiMethod method)
 {
     if (method.Visibility == CiVisibility.Private && method.CalledBy.Any(caller => caller.Class != method.Class))
     {
         method.Visibility = CiVisibility.Internal;
     }
 }
예제 #3
0
파일: GenPy.cs 프로젝트: haifenghuang/cito
        void WritePyDoc(CiMethod method)
        {
            if (method.Documentation == null)
            {
                return;
            }
            StartDoc(method.Documentation);
            bool first = true;

            foreach (CiVar param in method.Parameters)
            {
                if (param.Documentation != null)
                {
                    if (first)
                    {
                        WriteLine();
                        WriteLine();
                        first = false;
                    }
                    Write(":param ");
                    WriteName(param);
                    Write(": ");
                    Write(param.Documentation.Summary, false);
                    WriteLine();
                }
            }
            WriteLine("\"\"\"");
        }
예제 #4
0
파일: GenD.cs 프로젝트: epi/cito
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            Write(method.Documentation);
            bool paramsStarted = false;
            foreach (CiParam param in method.Signature.Params) {
            if (param.Documentation != null) {
                if (!paramsStarted) {
                    WriteLine("/// Params:");
                    paramsStarted = true;
                }
                Write("/// ");
                WriteVarName(param.Name);
                Write(" = ");
                Write(param.Documentation.Summary);
                WriteLine();
            }
            }

            Write(method.Visibility);
            switch (method.CallType) {
            case CiCallType.Static: Write("static "); break;
            case CiCallType.Normal: if (method.Visibility != CiVisibility.Private) Write("final "); break;
            case CiCallType.Abstract: Write("abstract "); break;
            case CiCallType.Virtual: break;
            case CiCallType.Override: Write("override "); break;
            }
            WriteSignature(method.Signature);
            if (method.CallType == CiCallType.Abstract)
            WriteLine(";");
            else {
            WriteLine();
            Write(method.Body);
            }
        }
예제 #5
0
파일: GenAs.cs 프로젝트: haifenghuang/ci
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            WriteDoc(method);
            WriteVisibility(method);
            switch (method.CallType)
            {
            case CiCallType.Static: Write("static "); break;

            case CiCallType.Normal: if (method.Visibility != CiVisibility.Private)
                {
                    Write("final ");
                }
                break;

            case CiCallType.Override: Write("override "); break;

            default: break;
            }
            Write("function ");
            WriteCamelCase(method.Name);
            Write('(');
            bool first = true;

            foreach (CiParam param in method.Signature.Params)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    Write(", ");
                }
                Write(param.Name);
                Write(param.Type);
            }
            Write(")");
            Write(method.Signature.ReturnType);
            WriteLine();
            OpenBlock();
            if (method.CallType == CiCallType.Abstract)
            {
                WriteLine("throw \"Abstract method called\";");
            }
            else
            {
                ICiStatement[] statements = method.Body.Statements;
                Write(statements);
                if (method.Signature.ReturnType != CiType.Void && statements.Length > 0)
                {
                    CiFor lastLoop = statements[statements.Length - 1] as CiFor;
                    if (lastLoop != null && lastLoop.Cond == null)
                    {
                        WriteLine("throw \"Unreachable\";");
                    }
                }
            }
            CloseBlock();
        }
예제 #6
0
파일: GenCCpp.cs 프로젝트: pfusik/cito
 protected static bool IsStringSubstring(CiExpr expr, out bool cast, out CiExpr ptr, out CiExpr offset, out CiExpr length)
 {
     if (expr is CiCallExpr call)
     {
         CiMethod method = (CiMethod)call.Method.Symbol;
         CiExpr[] args   = call.Arguments;
         if (method == CiSystem.StringSubstring && args.Length == 2)
         {
             cast   = false;
             ptr    = call.Method.Left;
             offset = args[0];
             length = args[1];
             return(true);
         }
         if (method == CiSystem.UTF8GetString)
         {
             cast   = true;
             ptr    = args[0];
             offset = args[1];
             length = args[2];
             return(true);
         }
     }
     cast   = false;
     ptr    = null;
     offset = null;
     length = null;
     return(false);
 }
예제 #7
0
        void Write(CiMethod method)
        {
            if (method.CallType == CiCallType.Abstract)
            {
                return;
            }
            WriteLine();
            Write(method.Class.Name);
            Write('.');
            if (method.CallType != CiCallType.Static)
            {
                Write("prototype.");
            }
            WriteCamelCase(method.Name);
            Write(" = function(");
            bool first = true;

            foreach (CiParam param in method.Signature.Params)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    Write(", ");
                }
                Write(param.Name);
            }
            Write(") ");
            Write(method.Body);
        }
예제 #8
0
        void WriteConstructor(CiClass klass)
        {
            // TODO: skip constructor if static methods only?

            if (klass.Visibility == CiVisibility.Public)
            {
                Write("=head2 C<$");
                WriteLowercase(klass.Name);
                Write(" = ");
                Write(this.Package);
                Write(klass.Name);
                WriteLine("-E<gt>new()>");
                WriteLine();
                if (klass.Constructor != null)
                {
                    Write(klass.Constructor.Documentation);
                }
                WriteLine("=cut");
                WriteLine();
            }

            IEnumerable <CiField> classStorageFields = klass.Members
                                                       .OfType <CiField>().Where(field => field.Type is CiClassStorageType);

            if (klass.Constructor == null && klass.BaseClass != null && !classStorageFields.Any())
            {
                // base constructor does the job
                return;
            }

            Write("sub new($) ");
            OpenBlock();
            if (klass.BaseClass != null)
            {
                WriteLine("my $self = shift()->SUPER::new();");
            }
            else
            {
                WriteLine("my $self = bless {}, shift;");
            }
            foreach (CiField field in classStorageFields)
            {
                Write("$self->{");
                WriteLowercaseWithUnderscores(field.Name);
                Write("} = ");
                WriteNew(field.Type);
                WriteLine(";");
            }
            if (klass.Constructor != null)
            {
                this.CurrentMethod = klass.Constructor;
                Write(klass.Constructor.Body.Statements);
                this.CurrentMethod = null;
            }
            WriteLine("return $self;");     // TODO: premature returns
            CloseBlock();
            WriteLine();
        }
예제 #9
0
 static void MarkDead(CiMethod method)
 {
     if (method.Visibility == CiVisibility.Private && method.CallType != CiCallType.Override && method.CalledBy.Count == 0)
     {
         method.Visibility = CiVisibility.Dead;
         foreach (CiMethod called in method.Calls)
         {
             called.CalledBy.Remove(method);
             MarkDead(called);
         }
     }
 }
예제 #10
0
 static void MarkThrows(CiMethod method)
 {
     if (method.Throws)
     {
         return;
     }
     method.Throws           = true;
     method.ErrorReturnValue = GetErrorValue(method.Signature.ReturnType);
     foreach (CiMethod calledBy in method.CalledBy)
     {
         MarkThrows(calledBy);
     }
 }
예제 #11
0
파일: GenD.cs 프로젝트: haifenghuang/ci
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            Write(method.Documentation);
            bool paramsStarted = false;

            foreach (CiParam param in method.Signature.Params)
            {
                if (param.Documentation != null)
                {
                    if (!paramsStarted)
                    {
                        WriteLine("/// Params:");
                        paramsStarted = true;
                    }
                    Write("/// ");
                    WriteVarName(param.Name);
                    Write(" = ");
                    Write(param.Documentation.Summary);
                    WriteLine();
                }
            }

            Write(method.Visibility);
            switch (method.CallType)
            {
            case CiCallType.Static: Write("static "); break;

            case CiCallType.Normal: if (method.Visibility != CiVisibility.Private)
                {
                    Write("final ");
                }
                break;

            case CiCallType.Abstract: Write("abstract "); break;

            case CiCallType.Virtual: break;

            case CiCallType.Override: Write("override "); break;
            }
            WriteSignature(method.Signature, method.Name);
            if (method.CallType == CiCallType.Abstract)
            {
                WriteLine(";");
            }
            else
            {
                WriteLine();
                Write(method.Body);
            }
        }
예제 #12
0
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteLocalName(method, CiPriority.Primary);
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.StringSubstring)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".substring(");
         args[0].Accept(this, CiPriority.Argument);
         if (args.Length == 2)
         {
             Write(", ");
             WriteAdd(args[0], args[1]);             // TODO: side effect
         }
         Write(')');
     }
     else if (obj.Type is CiArrayType && method.Name == "CopyTo")
     {
         AddLibrary(GenJsMethod.CopyArray,
                    "copyArray : function(sa, soffset, da, doffset, length)",
                    "if (typeof(sa.subarray) == \"function\" && typeof(da.set) == \"function\")",
                    "\tda.set(sa.subarray(soffset, soffset + length), doffset);",
                    "else",
                    "\tfor (let i = 0; i < length; i++)",
                    "\t\tda[doffset + i] = sa[soffset + i];");
         Write("Ci.copyArray(");
         obj.Accept(this, CiPriority.Argument);
         Write(", ");
         WriteArgs(method, args);
         Write(')');
     }
     else if (obj.Type is CiArrayType array && method.Name == "Fill")
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".fill(");
         args[0].Accept(this, CiPriority.Argument);
         if (args.Length == 3)
         {
             Write(", ");
             WriteStartEnd(args[1], args[2]);
         }
         Write(')');
     }
예제 #13
0
        protected void WriteArgs(CiMethod method, CiExpr[] args)
        {
            int i = 0;

            foreach (CiVar param in method.Parameters)
            {
                if (i >= args.Length)
                {
                    break;
                }
                if (i > 0)
                {
                    Write(", ");
                }
                WriteCoerced(param.Type, args[i++], CiPriority.Statement);
            }
        }
예제 #14
0
 static bool IsOverrideOf(CiMethod derived, CiMethod baseMethod)
 {
     if (derived == null || baseMethod == null)
     {
         return(false);
     }
     if (derived.CallType != CiCallType.Override && derived.CallType != CiCallType.Sealed)
     {
         return(false);
     }
     if (baseMethod.CallType == CiCallType.Static || baseMethod.CallType == CiCallType.Normal)
     {
         return(false);
     }
     // TODO: check parameter and return type
     baseMethod.Calls.Add(derived);
     return(true);
 }
예제 #15
0
 protected void WriteDoc(CiMethod method)
 {
     if (method.Documentation != null)
     {
         WriteDontClose(method.Documentation);
         foreach (CiParam param in method.Signature.Params)
         {
             if (param.Documentation != null)
             {
                 Write(" * @param ");
                 Write(param.Name);
                 Write(' ');
                 Write(param.Documentation.Summary);
                 WriteLine();
             }
         }
         WriteLine(" */");
     }
 }
예제 #16
0
파일: GenCCpp.cs 프로젝트: jellonek/cito
 protected void WriteMathCall(CiMethod method, CiExpr[] args)
 {
     if (method.Name == "Ceiling")
     {
         Write("ceil");
     }
     else if (method.Name == "FusedMultiplyAdd")
     {
         Write("fma");
     }
     else if (method.Name == "Truncate")
     {
         Write("trunc");
     }
     else
     {
         WriteLowercase(method.Name);
     }
     WriteArgsInParentheses(method, args);
 }
예제 #17
0
 protected void WriteDoc(CiMethod method)
 {
     if (method.Documentation == null)
     {
         return;
     }
     StartDoc(method.Documentation);
     WriteSelfDoc(method);
     foreach (CiVar param in method.Parameters)
     {
         if (param.Documentation != null)
         {
             Write(" * @param ");
             Write(param.Name);
             Write(' ');
             Write(param.Documentation.Summary);
             WriteLine();
         }
     }
     WriteLine(" */");
 }
예제 #18
0
파일: GenCpp.cs 프로젝트: jedwards1211/cito
 void WriteStringMethod(CiExpr obj, string name, CiMethod method, CiExpr[] args)
 {
     obj.Accept(this, CiPriority.Primary);
     if (obj is CiLiteral)
     {
         this.UsingStringViewLiterals = true;
         Write("sv");
     }
     Write('.');
     Write(name);
     if (IsOneAsciiString(args[0], out char c))
     {
         Write('(');
         WriteCharLiteral(c);
         Write(')');
     }
     else
     {
         WriteArgsInParentheses(method, args);
     }
 }
예제 #19
0
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            Write(method.Documentation);
            foreach (CiParam param in method.Signature.Params)
            {
                if (param.Documentation != null)
                {
                    Write("/// <param name=\"");
                    Write(param.Name);
                    Write("\">");
                    Write(param.Documentation.Summary);
                    WriteLine("</param>");
                }
            }

            Write(method.Visibility);
            switch (method.CallType)
            {
            case CiCallType.Static: Write("static "); break;

            case CiCallType.Normal: break;

            case CiCallType.Abstract: Write("abstract "); break;

            case CiCallType.Virtual: Write("virtual "); break;

            case CiCallType.Override: Write("override "); break;
            }
            WriteSignature(method.Signature);
            if (method.CallType == CiCallType.Abstract)
            {
                WriteLine(";");
            }
            else
            {
                WriteLine();
                Write(method.Body);
            }
        }
예제 #20
0
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            WriteDoc(method);
            if (method.CallType == CiCallType.Override)
            {
                WriteLine("@Override");
            }
            Write(method.Visibility);
            switch (method.CallType)
            {
            case CiCallType.Static: Write("static "); break;

            case CiCallType.Normal: if (method.Visibility != CiVisibility.Private)
                {
                    Write("final ");
                }
                break;

            case CiCallType.Abstract: Write("abstract "); break;

            default: break;
            }
            WriteSignature(method.Signature, method.Name);
            if (method.Throws)
            {
                Write(" throws Exception");
            }
            if (method.CallType == CiCallType.Abstract)
            {
                WriteLine(";");
            }
            else
            {
                WriteLine();
                Write(method.Body);
            }
        }
예제 #21
0
파일: GenCl.cs 프로젝트: jedwards1211/cito
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteCCall(null, method, args);
     }
     else if (obj.IsReferenceTo(CiSystem.MathClass))
     {
         WriteMathCall(method, args);
     }
     else if (method == CiSystem.ConsoleWrite)
     {
         WriteConsoleWrite(args, false);
     }
     else if (method == CiSystem.ConsoleWriteLine)
     {
         WriteConsoleWrite(args, true);
     }
     else
     {
         WriteCCall(obj, method, args);
     }
 }
예제 #22
0
 protected void WriteMathCall(CiMethod method, CiExpr[] args)
 {
     if (method == CiSystem.MathCeiling)
     {
         Write("ceil");
     }
     else if (method == CiSystem.MathFusedMultiplyAdd)
     {
         Write("fma");
     }
     else if (method == CiSystem.MathIsInfinity)
     {
         Write("isinf");
     }
     else if (method == CiSystem.MathTruncate)
     {
         Write("trunc");
     }
     else
     {
         WriteLowercase(method.Name);
     }
     WriteArgsInParentheses(method, args);
 }
예제 #23
0
파일: CiParser.cs 프로젝트: epi/cito
 CiMethod ParseConstructor()
 {
     OpenScope();
     CiMethod method = new CiMethod(
     CiType.Void, "<constructor>") {
     Class = this.CurrentClass,
     CallType = CiCallType.Normal,
     This = CreateThis()
     };
     this.CurrentMethod = method;
     method.Body = ParseBlock();
     CloseScope();
     this.CurrentMethod = null;
     return method;
 }
예제 #24
0
파일: CiParser.cs 프로젝트: epi/cito
 void ParseMethod(CiMethod method)
 {
     this.CurrentMethod = method;
     OpenScope();
     if (method.CallType != CiCallType.Static)
     method.This = CreateThis();
     method.Signature.Params = ParseParams();
     if (method.CallType == CiCallType.Abstract)
     Expect(CiToken.Semicolon);
     else
     method.Body = ParseBlock();
     CloseScope();
     this.CurrentMethod = null;
 }
예제 #25
0
파일: GenC.cs 프로젝트: epi/cito
 void Write(CiMethod method)
 {
     if (method.Visibility == CiVisibility.Dead || method.CallType == CiCallType.Abstract)
     return;
     WriteLine();
     this.CurrentMethod = method;
     WriteSignature(method);
     WriteLine();
     OpenBlock();
     ICiStatement[] statements = method.Body.Statements;
     StartBlock(statements);
     if (method.Throws && method.Signature.ReturnType == CiType.Void && method.Body.CompletesNormally) {
     if (!TryWriteCallAndReturn(statements, statements.Length - 1, null)) {
         Write(statements);
         WriteReturnTrue();
     }
     }
     else
     Write(statements);
     CloseBlock();
     this.CurrentMethod = null;
 }
예제 #26
0
파일: CiParser.cs 프로젝트: epi/cito
 CiClass ParseClass()
 {
     CiClass klass = new CiClass();
     klass.SourceFilename = this.Filename;
     if (Eat(CiToken.Abstract))
     klass.IsAbstract = true;
     Expect(CiToken.Class);
     klass.Name = ParseId();
     if (Eat(CiToken.Colon))
     klass.BaseClass = new CiUnknownClass { Name = ParseId() };
     Expect(CiToken.LeftBrace);
     OpenScope();
     this.CurrentClass = klass;
     klass.Members = this.Symbols;
     while (!Eat(CiToken.RightBrace)) {
     CiCodeDoc doc = ParseDoc();
     CiVisibility visibility = CiVisibility.Private;
     if (Eat(CiToken.Public))
         visibility = CiVisibility.Public;
     else if (Eat(CiToken.Internal))
         visibility = CiVisibility.Internal;
     CiSymbol symbol;
     if (See(CiToken.Const)) {
         symbol = ParseConst();
         ((CiConst) symbol).Class = klass;
     }
     else if (Eat(CiToken.Macro)) {
         if (visibility != CiVisibility.Private)
             throw new ParseException("Macros must be private");
         symbol = ParseMacro();
     }
     else {
         CiCallType callType;
         if (Eat(CiToken.Static))
             callType = CiCallType.Static;
         else if (Eat(CiToken.Abstract)) {
             if (!klass.IsAbstract)
                 throw new ParseException("Abstract methods only allowed in abstract classes");
             callType = CiCallType.Abstract;
             if (visibility == CiVisibility.Private)
                 visibility = CiVisibility.Internal;
         }
         else if (Eat(CiToken.Virtual)) {
             callType = CiCallType.Virtual;
             if (visibility == CiVisibility.Private)
                 visibility = CiVisibility.Internal;
         }
         else if (Eat(CiToken.Override)) {
             callType = CiCallType.Override;
             if (visibility == CiVisibility.Private)
                 visibility = CiVisibility.Internal;
         }
         else
             callType = CiCallType.Normal;
         CiType type = ParseReturnType();
         if (type is CiClassStorageType && See(CiToken.LeftBrace)) {
             if (type.Name != klass.Name)
                 throw new ParseException("{0}() looks like a constructor, but it is in a different class {1}", type.Name, klass.Name);
             if (callType != CiCallType.Normal)
                 throw new ParseException("Constructor cannot be static, abstract, virtual or override");
             if (klass.Constructor != null)
                 throw new ParseException("Duplicate constructor");
             klass.Constructor = ParseConstructor();
             continue;
         }
         string name = ParseId();
         if (See(CiToken.LeftParenthesis)) {
             CiMethod method = new CiMethod(type, name) {
                 Class = klass,
                 CallType = callType
             };
             ParseMethod(method);
             symbol = method;
         }
         else {
             if (visibility != CiVisibility.Private)
                 throw new ParseException("Fields must be private");
             if (callType != CiCallType.Normal)
                 throw new ParseException("Fields cannot be static, abstract, virtual or override");
             if (type == CiType.Void)
                 throw new ParseException("Field is void");
             Expect(CiToken.Semicolon);
             symbol = new CiField { Class = klass, Type = type, Name = name };
         }
     }
     symbol.Documentation = doc;
     symbol.Visibility = visibility;
     klass.Members.Add(symbol);
     }
     this.CurrentClass = null;
     CloseScope();
     klass.ConstArrays = this.ConstArrays.ToArray();
     this.ConstArrays.Clear();
     return klass;
 }
예제 #27
0
파일: CiResolver.cs 프로젝트: epi/cito
 static void MarkDead(CiMethod method)
 {
     if (method.Visibility == CiVisibility.Private && method.CallType != CiCallType.Override && method.CalledBy.Count == 0) {
     method.Visibility = CiVisibility.Dead;
     foreach (CiMethod called in method.Calls) {
         called.CalledBy.Remove(method);
         MarkDead(called);
     }
     }
 }
예제 #28
0
파일: GenAs.cs 프로젝트: haifenghuang/ci
 protected override void WriteName(CiMethod method)
 {
     WriteCamelCase(method.Name);
 }
예제 #29
0
파일: GenTs.cs 프로젝트: pfusik/cito
        void Write(CiClass klass, CiMethod method)
        {
            WriteDoc(method);
            Write(method.Visibility);
            switch (method.CallType)
            {
            case CiCallType.Static:
                Write("static ");
                break;

            case CiCallType.Virtual:
                break;

            case CiCallType.Abstract:
                Write("abstract ");
                break;

            case CiCallType.Override:
                break;

            case CiCallType.Normal:
                // no final methods in TS
                break;

            case CiCallType.Sealed:
                // no final methods in TS
                break;

            default:
                throw new NotImplementedException(method.CallType.ToString());
            }
            WriteName(method);
            Write('(');
            int i = 0;

            foreach (CiVar param in method.Parameters)
            {
                if (i > 0)
                {
                    Write(", ");
                }
                WriteName(param);
                if (param.Value != null && !this.GenFullCode)
                {
                    Write('?');
                }
                Write(": ");
                Write(param.Type);
                if (param.Value != null && this.GenFullCode)
                {
                    WriteVarInit(param);
                }
                i++;
            }
            Write("): ");
            Write(method.Type);
            if (this.GenFullCode)
            {
                WriteBody(method);
            }
            else
            {
                WriteLine(';');
            }
        }
예제 #30
0
파일: GenPerl5.cs 프로젝트: epi/cito
	void Write(CiMethod method)
	{
		if (method.Visibility == CiVisibility.Public) {
			Write("=head2 C<");
			if (method.CallType == CiCallType.Static) {
				Write(this.Package);
				Write(method.Class.Name);
				Write("::");
			}
			else {
				Write('$');
				WriteLowercase(method.Class.Name);
				Write("-E<gt>");
			}
			WriteLowercaseWithUnderscores(method.Name);
			Write('(');
			bool first = true;
			foreach (CiParam param in method.Signature.Params) {
				if (first)
					first = false;
				else
					Write(", ");
				WriteDocName(param);
			}
			WriteLine(")>");
			WriteLine();
			Write(method.Documentation);
			if (method.Signature.Params.Any(param => param.Documentation != null)) {
				WriteLine("Parameters:");
				WriteLine();
				WriteLine("=over");
				WriteLine();
				foreach (CiParam param in method.Signature.Params) {
					Write("=item ");
					WriteDocName(param);
					WriteLine();
					WriteLine();
					Write(param.Documentation);
				}
				WriteLine("=back");
				WriteLine();
			}
			WriteLine("=cut");
			WriteLine();
		}
		if (method.CallType == CiCallType.Abstract)
			return;
		this.CurrentMethod = method;
		Write("sub ");
		WriteLowercaseWithUnderscores(method.Name);
		Write('(');
		if (method.CallType != CiCallType.Static)
			Write('$');
		foreach (CiParam param in method.Signature.Params)
			Write('$');
		Write(") ");
		OpenBlock();
		if (method.CallType != CiCallType.Static || method.Signature.Params.Length > 0) {
			Write("my (");
			bool first = true;
			if (method.CallType != CiCallType.Static) {
				Write("$self");
				first = false;
			}
			foreach (CiParam param in method.Signature.Params) {
				if (first)
					first = false;
				else
					Write(", ");
				Write('$');
				Write(param.Name);
			}
			WriteLine(") = @_;");
		}
		Write(method.Body.Statements);
		CloseBlock();
		WriteLine();
		this.CurrentMethod = null;
	}
예제 #31
0
파일: CiResolver.cs 프로젝트: epi/cito
 void ICiSymbolVisitor.Visit(CiMethod method)
 {
     this.CurrentMethod = method;
     Resolve(method.Signature);
     if (method.CallType != CiCallType.Abstract) {
     Resolve(method.Body);
     if (method.Signature.ReturnType != CiType.Void && method.Body.CompletesNormally)
         throw new ResolveException("Method can complete without a return value");
     }
     this.CurrentMethod = null;
 }
예제 #32
0
        CiType LookupType(string name)
        {
            CiSymbol symbol = this.Symbols.TryLookup(name);

            if (symbol is CiType)
            {
                return((CiType)symbol);
            }
            if (symbol is CiClass)
            {
                return new CiClassPtrType {
                           Name = name, Class = (CiClass)symbol
                }
            }
            ;
            if (symbol == null)
            {
                CiType unknown = new CiUnknownType();

                unknown.Name = name;
                return(unknown);
            }
            throw new ParseException("{0} is not a type", name);
        }

        CiType ParseArrayType(CiType baseType)
        {
            if (Eat(CiToken.LeftBracket))
            {
                if (Eat(CiToken.RightBracket))
                {
                    return new CiArrayPtrType {
                               ElementType = ParseArrayType(baseType)
                    }
                }
                ;
                CiExpr len = ParseExpr();
                Expect(CiToken.RightBracket);
                return(new CiArrayStorageType {
                    LengthExpr = len,
                    ElementType = ParseArrayType(baseType)
                });
            }
            return(baseType);
        }

        CiType ParseType()
        {
            string baseName = ParseId();
            CiType baseType;

            if (Eat(CiToken.LeftParenthesis))
            {
                if (baseName == "string")
                {
                    baseType = new CiStringStorageType {
                        LengthExpr = ParseExpr()
                    };

                    Expect(CiToken.RightParenthesis);
                }
                else
                {
                    Expect(CiToken.RightParenthesis);
                    baseType = new CiClassStorageType {
                        Name = baseName, Class = new CiUnknownClass {
                            Name = baseName
                        }
                    };
                }
            }
            else
            {
                baseType = LookupType(baseName);
            }
            return(ParseArrayType(baseType));
        }

        object ParseConstInitializer(CiType type)
        {
            if (type is CiArrayType)
            {
                Expect(CiToken.LeftBrace);
                CiType        elementType = ((CiArrayType)type).ElementType;
                List <object> list        = new List <object>();
                if (!See(CiToken.RightBrace))
                {
                    do
                    {
                        list.Add(ParseConstInitializer(elementType));
                    }while (Eat(CiToken.Comma));
                }
                Expect(CiToken.RightBrace);
                return(list.ToArray());
            }
            return(ParseExpr());
        }

        CiConst ParseConst()
        {
            Expect(CiToken.Const);
            CiConst konst = new CiConst();

            konst.Type = ParseType();
            konst.Name = ParseId();
            Expect(CiToken.Assign);
            konst.Value = ParseConstInitializer(konst.Type);
            Expect(CiToken.Semicolon);
            if (this.Symbols.Parent != null && konst.Type is CiArrayType)
            {
                this.ConstArrays.Add(konst);
                konst.GlobalName = "CiConstArray_" + this.ConstArrays.Count;
            }
            return(konst);
        }

        CiBinaryResourceExpr ParseBinaryResource()
        {
            Expect(CiToken.LeftParenthesis);
            CiExpr nameExpr = ParseExpr();

            Expect(CiToken.RightParenthesis);
            return(new CiBinaryResourceExpr {
                NameExpr = nameExpr
            });
        }

        CiExpr ParsePrimaryExpr()
        {
            if (See(CiToken.Increment) || See(CiToken.Decrement) || See(CiToken.Minus) || See(CiToken.Not))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                CiExpr inner = ParsePrimaryExpr();
                return(new CiUnaryExpr {
                    Op = op, Inner = inner
                });
            }
            if (Eat(CiToken.CondNot))
            {
                CiExpr inner = ParsePrimaryExpr();
                return(new CiCondNotExpr {
                    Inner = inner
                });
            }
            CiExpr result;

            if (See(CiToken.IntConstant))
            {
                result = new CiConstExpr(this.CurrentInt);
                NextToken();
            }
            else if (See(CiToken.StringConstant))
            {
                result = new CiConstExpr(this.CurrentString);
                NextToken();
            }
            else if (Eat(CiToken.LeftParenthesis))
            {
                result = ParseExpr();
                Expect(CiToken.RightParenthesis);
            }
            else if (See(CiToken.Id))
            {
                string name = ParseId();
                if (name == "BinaryResource")
                {
                    result = ParseBinaryResource();
                }
                else
                {
                    CiSymbol symbol = this.Symbols.TryLookup(name);
                    if (symbol is CiMacro)
                    {
                        Expand((CiMacro)symbol);
                        Expect(CiToken.LeftParenthesis);
                        result = ParseExpr();
                        Expect(CiToken.RightParenthesis);
                    }
                    else
                    {
                        if (symbol == null)
                        {
                            symbol = new CiUnknownSymbol {
                                Name = name
                            }
                        }
                        ;
                        result = new CiSymbolAccess {
                            Symbol = symbol
                        };
                    }
                }
            }
            else if (Eat(CiToken.New))
            {
                CiType newType = ParseType();
                if (!(newType is CiClassStorageType || newType is CiArrayStorageType))
                {
                    throw new ParseException("'new' syntax error");
                }
                result = new CiNewExpr {
                    NewType = newType
                };
            }
            else
            {
                throw new ParseException("Invalid expression");
            }
            for (;;)
            {
                if (Eat(CiToken.Dot))
                {
                    result = new CiUnknownMemberAccess {
                        Parent = result, Name = ParseId()
                    }
                }
                ;
                else if (Eat(CiToken.LeftParenthesis))
                {
                    CiMethodCall call = new CiMethodCall();
                    call.Obj = result;
                    List <CiExpr> args = new List <CiExpr>();
                    if (!See(CiToken.RightParenthesis))
                    {
                        do
                        {
                            args.Add(ParseExpr());
                        }while (Eat(CiToken.Comma));
                    }
                    Expect(CiToken.RightParenthesis);
                    call.Arguments = args.ToArray();
                    result         = call;
                }
                else if (Eat(CiToken.LeftBracket))
                {
                    CiExpr index = ParseExpr();
                    Expect(CiToken.RightBracket);
                    result = new CiIndexAccess {
                        Parent = result, Index = index
                    };
                }
                else if (See(CiToken.Increment) || See(CiToken.Decrement))
                {
                    CiToken op = this.CurrentToken;
                    NextToken();
                    return(new CiPostfixExpr {
                        Inner = result, Op = op
                    });
                }
                else
                {
                    return(result);
                }
            }
        }

        CiExpr ParseMulExpr()
        {
            CiExpr left = ParsePrimaryExpr();

            while (See(CiToken.Asterisk) || See(CiToken.Slash) || See(CiToken.Mod))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                left = new CiBinaryExpr {
                    Left = left, Op = op, Right = ParsePrimaryExpr()
                };
            }
            return(left);
        }

        CiExpr ParseAddExpr()
        {
            CiExpr left = ParseMulExpr();

            while (See(CiToken.Plus) || See(CiToken.Minus))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                left = new CiBinaryExpr {
                    Left = left, Op = op, Right = ParseMulExpr()
                };
            }
            return(left);
        }

        CiExpr ParseShiftExpr()
        {
            CiExpr left = ParseAddExpr();

            while (See(CiToken.ShiftLeft) || See(CiToken.ShiftRight))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                left = new CiBinaryExpr {
                    Left = left, Op = op, Right = ParseAddExpr()
                };
            }
            return(left);
        }

        CiExpr ParseRelExpr()
        {
            CiExpr left = ParseShiftExpr();

            while (See(CiToken.Less) || See(CiToken.LessOrEqual) || See(CiToken.Greater) || See(CiToken.GreaterOrEqual))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                left = new CiBoolBinaryExpr {
                    Left = left, Op = op, Right = ParseShiftExpr()
                };
            }
            return(left);
        }

        CiExpr ParseEqualityExpr()
        {
            CiExpr left = ParseRelExpr();

            while (See(CiToken.Equal) || See(CiToken.NotEqual))
            {
                CiToken op = this.CurrentToken;
                NextToken();
                left = new CiBoolBinaryExpr {
                    Left = left, Op = op, Right = ParseRelExpr()
                };
            }
            return(left);
        }

        CiExpr ParseAndExpr()
        {
            CiExpr left = ParseEqualityExpr();

            while (Eat(CiToken.And))
            {
                left = new CiBinaryExpr {
                    Left = left, Op = CiToken.And, Right = ParseEqualityExpr()
                }
            }
            ;
            return(left);
        }

        CiExpr ParseXorExpr()
        {
            CiExpr left = ParseAndExpr();

            while (Eat(CiToken.Xor))
            {
                left = new CiBinaryExpr {
                    Left = left, Op = CiToken.Xor, Right = ParseAndExpr()
                }
            }
            ;
            return(left);
        }

        CiExpr ParseOrExpr()
        {
            CiExpr left = ParseXorExpr();

            while (Eat(CiToken.Or))
            {
                left = new CiBinaryExpr {
                    Left = left, Op = CiToken.Or, Right = ParseXorExpr()
                }
            }
            ;
            return(left);
        }

        CiExpr ParseCondAndExpr()
        {
            CiExpr left = ParseOrExpr();

            while (Eat(CiToken.CondAnd))
            {
                left = new CiBoolBinaryExpr {
                    Left = left, Op = CiToken.CondAnd, Right = ParseOrExpr()
                }
            }
            ;
            return(left);
        }

        CiExpr ParseCondOrExpr()
        {
            CiExpr left = ParseCondAndExpr();

            while (Eat(CiToken.CondOr))
            {
                left = new CiBoolBinaryExpr {
                    Left = left, Op = CiToken.CondOr, Right = ParseCondAndExpr()
                }
            }
            ;
            return(left);
        }

        CiExpr ParseExpr()
        {
            CiExpr left = ParseCondOrExpr();

            if (Eat(CiToken.QuestionMark))
            {
                CiCondExpr result = new CiCondExpr();
                result.Cond   = left;
                result.OnTrue = ParseExpr();
                Expect(CiToken.Colon);
                result.OnFalse = ParseExpr();
                return(result);
            }
            return(left);
        }

        CiMaybeAssign ParseMaybeAssign()
        {
            CiExpr  left = ParseExpr();
            CiToken op   = this.CurrentToken;

            if (op == CiToken.Assign || op == CiToken.AddAssign || op == CiToken.SubAssign || op == CiToken.MulAssign || op == CiToken.DivAssign || op == CiToken.ModAssign ||
                op == CiToken.AndAssign || op == CiToken.OrAssign || op == CiToken.XorAssign || op == CiToken.ShiftLeftAssign || op == CiToken.ShiftRightAssign)
            {
                NextToken();
                CiAssign result = new CiAssign();
                result.Target = left;
                result.Op     = op;
                result.Source = ParseMaybeAssign();
                return(result);
            }
            return(left);
        }

        ICiStatement ParseExprWithSideEffect()
        {
            ICiStatement result = ParseMaybeAssign() as ICiStatement;

            if (result == null)
            {
                throw new ParseException("Useless expression");
            }
            return(result);
        }

        CiExpr ParseCond()
        {
            Expect(CiToken.LeftParenthesis);
            CiExpr cond = ParseExpr();

            Expect(CiToken.RightParenthesis);
            return(cond);
        }

        void OpenScope()
        {
            this.Symbols = new SymbolTable {
                Parent = this.Symbols
            };
        }

        void CloseScope()
        {
            this.Symbols = this.Symbols.Parent;
        }

        CiVar ParseVar()
        {
            CiVar def = new CiVar();

            def.Type = ParseType();
            def.Name = ParseId();
            if (Eat(CiToken.Assign))
            {
                def.InitialValue = ParseExpr();
            }
            Expect(CiToken.Semicolon);
            this.Symbols.Add(def);
            return(def);
        }

        ICiStatement ParseVarOrExpr()
        {
            string   name   = this.CurrentString;
            CiSymbol symbol = this.Symbols.TryLookup(name);

            if (symbol is CiMacro)
            {
                NextToken();
                Expand((CiMacro)symbol);
                return(ParseStatement());
            }
            // try var
            StringBuilder sb = new StringBuilder();

            this.CopyTo = sb;
            try {
                return(ParseVar());
            }
            catch (ParseException) {
            }
            finally {
                this.CopyTo = null;
            }

            // try expr
            this.CurrentString = name;
            this.CurrentToken  = CiToken.Id;
            BeginExpand("ambigous code", sb.ToString(), null);
            SetReader(new StringReader(sb.ToString()));
            ICiStatement result = ParseExprWithSideEffect();

            Expect(CiToken.Semicolon);
            return(result);
        }

        CiNativeBlock ParseNativeBlock()
        {
            StringBuilder sb = new StringBuilder();

            this.CopyTo = sb;
            NextToken();
            bool oneLine = true;

            try {
                if (See(CiToken.LeftBrace))
                {
                    oneLine     = false;
                    sb          = new StringBuilder();
                    this.CopyTo = sb;
                    Expect(CiToken.LeftBrace);
                }
                int level = 1;
                for (;;)
                {
                    if (oneLine && See(CiToken.Semicolon) && level == 1)
                    {
                        break;
                    }
                    if (See(CiToken.EndOfFile))
                    {
                        throw new ParseException("Native block not terminated");
                    }
                    if (See(CiToken.LeftBrace))
                    {
                        level++;
                    }
                    else if (See(CiToken.RightBrace))
                    {
                        if (--level == 0)
                        {
                            break;
                        }
                    }
                    NextToken();
                }
            }
            finally {
                this.CopyTo = null;
            }
            NextToken();
            Trace.Assert(sb[sb.Length - 1] == '}');
            if (!oneLine)
            {
                sb.Length--;
            }
            else
            {
                sb.Append("\n\t");
            }

            return(new CiNativeBlock {
                Content = sb.ToString()
            });
        }

        CiSwitch ParseSwitch()
        {
            Expect(CiToken.LeftParenthesis);
            CiSwitch result = new CiSwitch();

            result.Value = ParseExpr();
            Expect(CiToken.RightParenthesis);
            Expect(CiToken.LeftBrace);

            List <CiCase> cases = new List <CiCase>();

            while (Eat(CiToken.Case))
            {
                List <object> values = new List <object>();
                do
                {
                    values.Add(ParseExpr());
                    Expect(CiToken.Colon);
                } while (Eat(CiToken.Case));
                if (See(CiToken.Default))
                {
                    throw new ParseException("Please remove case before default");
                }
                CiCase kase = new CiCase {
                    Values = values.ToArray()
                };

                List <ICiStatement> statements = new List <ICiStatement>();
                do
                {
                    statements.Add(ParseStatement());
                }while (!See(CiToken.Case) && !See(CiToken.Default) && !See(CiToken.Goto) && !See(CiToken.RightBrace));
                kase.Body = statements.ToArray();

                if (Eat(CiToken.Goto))
                {
                    if (Eat(CiToken.Case))
                    {
                        kase.FallthroughTo = ParseExpr();
                    }
                    else if (Eat(CiToken.Default))
                    {
                        kase.FallthroughTo = null;
                    }
                    else
                    {
                        throw new ParseException("Expected goto case or goto default");
                    }
                    Expect(CiToken.Semicolon);
                    kase.Fallthrough = true;
                }
                cases.Add(kase);
            }
            if (cases.Count == 0)
            {
                throw new ParseException("Switch with no cases");
            }
            result.Cases = cases.ToArray();

            if (Eat(CiToken.Default))
            {
                Expect(CiToken.Colon);
                List <ICiStatement> statements = new List <ICiStatement>();
                do
                {
                    statements.Add(ParseStatement());
                }while (!See(CiToken.RightBrace));
                result.DefaultBody = statements.ToArray();
            }

            Expect(CiToken.RightBrace);
            return(result);
        }

        ICiStatement ParseStatement()
        {
            while (Eat(CiToken.Macro))
            {
                this.Symbols.Add(ParseMacro());
            }
            if (See(CiToken.Id))
            {
                return(ParseVarOrExpr());
            }
            if (See(CiToken.LeftBrace))
            {
                OpenScope();
                CiBlock result = ParseBlock();
                CloseScope();
                return(result);
            }
            if (Eat(CiToken.Break))
            {
                Expect(CiToken.Semicolon);
                return(new CiBreak());
            }
            if (See(CiToken.Const))
            {
                CiConst konst = ParseConst();
                this.Symbols.Add(konst);
                return(konst);
            }
            if (Eat(CiToken.Continue))
            {
                Expect(CiToken.Semicolon);
                return(new CiContinue());
            }
            if (Eat(CiToken.Delete))
            {
                CiExpr expr = ParseExpr();
                Expect(CiToken.Semicolon);
                return(new CiDelete {
                    Expr = expr
                });
            }
            if (Eat(CiToken.Do))
            {
                CiDoWhile result = new CiDoWhile();
                result.Body = ParseStatement();
                Expect(CiToken.While);
                result.Cond = ParseCond();
                Expect(CiToken.Semicolon);
                return(result);
            }
            if (Eat(CiToken.For))
            {
                Expect(CiToken.LeftParenthesis);
                OpenScope();
                CiFor result = new CiFor();
                if (See(CiToken.Id))
                {
                    result.Init = ParseVarOrExpr();
                }
                else
                {
                    Expect(CiToken.Semicolon);
                }
                if (!See(CiToken.Semicolon))
                {
                    result.Cond = ParseExpr();
                }
                Expect(CiToken.Semicolon);
                if (!See(CiToken.RightParenthesis))
                {
                    result.Advance = ParseExprWithSideEffect();
                }
                Expect(CiToken.RightParenthesis);
                result.Body = ParseStatement();
                CloseScope();
                return(result);
            }
            if (Eat(CiToken.If))
            {
                CiIf result = new CiIf();
                result.Cond   = ParseCond();
                result.OnTrue = ParseStatement();
                if (Eat(CiToken.Else))
                {
                    result.OnFalse = ParseStatement();
                }
                return(result);
            }
            if (See(CiToken.Native))
            {
                return(ParseNativeBlock());
            }
            if (Eat(CiToken.Return))
            {
                CiReturn result = new CiReturn();
                if (this.CurrentMethod.Signature.ReturnType != CiType.Void)
                {
                    result.Value = ParseExpr();
                }
                Expect(CiToken.Semicolon);
                return(result);
            }
            if (Eat(CiToken.Switch))
            {
                return(ParseSwitch());
            }
            if (Eat(CiToken.Throw))
            {
                CiThrow result = new CiThrow();
                result.Message = ParseExpr();
                Expect(CiToken.Semicolon);
                return(result);
            }
            if (Eat(CiToken.While))
            {
                CiWhile result = new CiWhile();
                result.Cond = ParseCond();
                result.Body = ParseStatement();
                return(result);
            }
            throw new ParseException("Invalid statement");
        }

        CiBlock ParseBlock()
        {
            Expect(CiToken.LeftBrace);
            List <ICiStatement> statements = new List <ICiStatement>();

            while (!Eat(CiToken.RightBrace))
            {
                statements.Add(ParseStatement());
            }
            return(new CiBlock {
                Statements = statements.ToArray()
            });
        }

        CiParam CreateThis()
        {
            CiParam thiz = new CiParam();

            thiz.Type = new CiClassPtrType {
                Name = this.CurrentClass.Name, Class = this.CurrentClass
            };
            thiz.Name = "this";
            this.Symbols.Add(thiz);
            return(thiz);
        }

        CiType ParseReturnType()
        {
            if (Eat(CiToken.Void))
            {
                return(CiType.Void);
            }
            return(ParseType());
        }

        CiParam[] ParseParams()
        {
            Expect(CiToken.LeftParenthesis);
            List <CiParam> paramz = new List <CiParam>();

            if (!See(CiToken.RightParenthesis))
            {
                do
                {
                    CiParam param = new CiParam();
                    param.Documentation = ParseDoc();
                    param.Type          = ParseType();
                    param.Name          = ParseId();
                    this.Symbols.Add(param);
                    paramz.Add(param);
                } while (Eat(CiToken.Comma));
            }
            Expect(CiToken.RightParenthesis);
            return(paramz.ToArray());
        }

        void ParseMethod(CiMethod method)
        {
            this.CurrentMethod = method;
            OpenScope();
            if (method.CallType != CiCallType.Static)
            {
                method.This = CreateThis();
            }
            method.Signature.Params = ParseParams();
            if (method.CallType == CiCallType.Abstract)
            {
                Expect(CiToken.Semicolon);
            }
            else
            {
                method.Body = ParseBlock();
            }
            CloseScope();
            this.CurrentMethod = null;
        }

        CiMethod ParseConstructor()
        {
            NextToken();
            Expect(CiToken.LeftParenthesis);
            Expect(CiToken.RightParenthesis);
            OpenScope();
            CiMethod method = new CiMethod(
                CiType.Void, "<constructor>")
            {
                Class    = this.CurrentClass,
                CallType = CiCallType.Normal,
                This     = CreateThis()
            };

            this.CurrentMethod = method;
            method.Body        = ParseBlock();
            CloseScope();
            this.CurrentMethod = null;
            return(method);
        }

        CiClass ParseClass()
        {
            CiClass klass = new CiClass();

            klass.SourceFilename = this.Filename;
            if (Eat(CiToken.Abstract))
            {
                klass.IsAbstract = true;
            }
            Expect(CiToken.Class);
            klass.Name = ParseId();
            if (Eat(CiToken.Colon))
            {
                klass.BaseClass = new CiUnknownClass {
                    Name = ParseId()
                }
            }
            ;
            Expect(CiToken.LeftBrace);
            OpenScope();
            this.CurrentClass = klass;
            klass.Members     = this.Symbols;
            while (!Eat(CiToken.RightBrace))
            {
                CiCodeDoc    doc        = ParseDoc();
                CiVisibility visibility = CiVisibility.Private;
                if (Eat(CiToken.Public))
                {
                    visibility = CiVisibility.Public;
                }
                else if (Eat(CiToken.Internal))
                {
                    visibility = CiVisibility.Internal;
                }
                CiSymbol symbol;
                if (See(CiToken.Const))
                {
                    symbol = ParseConst();
                    ((CiConst)symbol).Class = klass;
                }
                else if (Eat(CiToken.Macro))
                {
                    if (visibility != CiVisibility.Private)
                    {
                        throw new ParseException("Macros must be private");
                    }
                    symbol = ParseMacro();
                }
                else
                {
                    if (See(CiToken.Id) && this.CurrentString == klass.Name)
                    {
                        if (klass.Constructor != null)
                        {
                            throw new ParseException("Duplicate constructor");
                        }
                        klass.Constructor = ParseConstructor();
                        continue;
                    }
                    CiCallType callType;
                    if (Eat(CiToken.Static))
                    {
                        callType = CiCallType.Static;
                    }
                    else if (Eat(CiToken.Abstract))
                    {
                        if (!klass.IsAbstract)
                        {
                            throw new ParseException("Abstract methods only allowed in abstract classes");
                        }
                        callType = CiCallType.Abstract;
                        if (visibility == CiVisibility.Private)
                        {
                            visibility = CiVisibility.Internal;
                        }
                    }
                    else if (Eat(CiToken.Virtual))
                    {
                        callType = CiCallType.Virtual;
                        if (visibility == CiVisibility.Private)
                        {
                            visibility = CiVisibility.Internal;
                        }
                    }
                    else if (Eat(CiToken.Override))
                    {
                        callType = CiCallType.Override;
                        if (visibility == CiVisibility.Private)
                        {
                            visibility = CiVisibility.Internal;
                        }
                    }
                    else
                    {
                        callType = CiCallType.Normal;
                    }
                    CiType type = ParseReturnType();
                    string name = ParseId();
                    if (See(CiToken.LeftParenthesis))
                    {
                        CiMethod method = new CiMethod(type, name)
                        {
                            Class    = klass,
                            CallType = callType
                        };
                        ParseMethod(method);
                        symbol = method;
                    }
                    else
                    {
                        if (visibility != CiVisibility.Private)
                        {
                            throw new ParseException("Fields must be private");
                        }
                        if (callType != CiCallType.Normal)
                        {
                            throw new ParseException("Fields cannot be static, abstract, virtual or override");
                        }
                        if (type == CiType.Void)
                        {
                            throw new ParseException("Field is void");
                        }
                        Expect(CiToken.Semicolon);
                        symbol = new CiField {
                            Class = klass, Type = type, Name = name
                        };
                    }
                }
                symbol.Documentation = doc;
                symbol.Visibility    = visibility;
                klass.Members.Add(symbol);
            }
            this.CurrentClass = null;
            CloseScope();
            klass.ConstArrays = this.ConstArrays.ToArray();
            this.ConstArrays.Clear();
            return(klass);
        }

        CiDelegate ParseDelegate()
        {
            CiDelegate del = new CiDelegate();

            Expect(CiToken.Delegate);
            del.ReturnType = ParseReturnType();
            del.Name       = ParseId();
            OpenScope();
            del.Params = ParseParams();
            CloseScope();
            Expect(CiToken.Semicolon);
            return(del);
        }

        public void Parse(string filename, TextReader reader)
        {
            Open(filename, reader);
            while (!See(CiToken.EndOfFile))
            {
                CiCodeDoc doc = ParseDoc();
                bool      pub = Eat(CiToken.Public);
                CiSymbol  symbol;
                if (See(CiToken.Enum))
                {
                    symbol = ParseEnum();
                }
                else if (See(CiToken.Class) || See(CiToken.Abstract))
                {
                    symbol = ParseClass();
                }
                else if (See(CiToken.Delegate))
                {
                    symbol = ParseDelegate();
                }
                else
                {
                    throw new ParseException("Expected class, enum or delegate");
                }
                symbol.Documentation = doc;
                symbol.Visibility    = pub ? CiVisibility.Public : CiVisibility.Internal;
                this.Symbols.Add(symbol);
            }
        }

        public CiProgram Program
        {
            get
            {
                return(new CiProgram {
                    Globals = this.Symbols
                });
            }
        }
    }
}
예제 #33
0
파일: GenJs.cs 프로젝트: 00mjk/cito
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteLocalName(method, CiPriority.Primary);
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.StringSubstring)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".substring(");
         args[0].Accept(this, CiPriority.Statement);
         if (args.Length == 2)
         {
             Write(", ");
             WriteAdd(args[0], args[1]);             // TODO: side effect
         }
         Write(')');
     }
     else if (obj.Type is CiArrayType && method.Name == "CopyTo")
     {
         AddLibrary(GenJsMethod.CopyArray,
                    "copyArray : function(sa, soffset, da, doffset, length)",
                    "if (typeof(sa.subarray) == \"function\" && typeof(da.set) == \"function\")",
                    "\tda.set(sa.subarray(soffset, soffset + length), doffset);",
                    "else",
                    "\tfor (let i = 0; i < length; i++)",
                    "\t\tda[doffset + i] = sa[soffset + i];");
         Write("Ci.copyArray(");
         obj.Accept(this, CiPriority.Statement);
         Write(", ");
         WriteArgs(method, args);
         Write(')');
     }
     else if (method == CiSystem.CollectionClear)
     {
         if (obj.Type is CiDictionaryType)
         {
             Write("for (const key in ");
             obj.Accept(this, CiPriority.Statement);
             WriteLine(')');
             Write("\tdelete ");
             obj.Accept(this, CiPriority.Primary);             // FIXME: side effect
             Write("[key];");
         }
         else
         {
             obj.Accept(this, CiPriority.Primary);
             Write(".length = 0");
         }
     }
     else if (WriteListAddInsert(obj, method, args, "push", "splice", ", 0, "))
     {
         // done
     }
     else if (method == CiSystem.ListRemoveAt)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".splice(");
         args[0].Accept(this, CiPriority.Statement);
         Write(", 1)");
     }
     else if (method == CiSystem.ListRemoveRange)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".splice(");
         args[0].Accept(this, CiPriority.Statement);
         Write(", ");
         args[1].Accept(this, CiPriority.Statement);
         Write(')');
     }
     else if (obj.Type is CiDictionaryType dict && method.Name == "Add")
     {
         if (parent > CiPriority.Assign)
         {
             Write('(');
         }
         obj.Accept(this, CiPriority.Primary);
         Write('[');
         args[0].Accept(this, CiPriority.Statement);
         Write("] = ");
         WriteNewStorage(dict.ValueType);
         if (parent > CiPriority.Assign)
         {
             Write(')');
         }
     }
예제 #34
0
파일: GenC.cs 프로젝트: epi/cito
 void WriteSignature(CiMethod method)
 {
     if (method.Visibility != CiVisibility.Public)
     Write("static ");
     var paramz = method.Signature.Params.Select(param => ToString(param.Type, param.Name));
     if (method.CallType != CiCallType.Static)
     paramz = new string[1] { ToString(method.This.Type, "self") }.Concat(paramz);
     string s = paramz.Any() ? string.Join(", ", paramz.ToArray()) : "void";
     s = method.Class.Name + "_" + method.Name + "(" + s + ")";
     CiType type = method.Signature.ReturnType;
     if (method.Throws && type == CiType.Void)
     type = CiBoolType.Value;
     Write(type, s);
 }
예제 #35
0
파일: GenJava.cs 프로젝트: epi/cito
 protected override void WriteName(CiMethod method)
 {
     WriteCamelCase(method.Name);
 }
예제 #36
0
파일: SourceGenerator.cs 프로젝트: epi/cito
 protected void WriteDoc(CiMethod method)
 {
     if (method.Documentation != null) {
     WriteDontClose(method.Documentation);
     foreach (CiParam param in method.Signature.Params) {
         if (param.Documentation != null) {
             Write(" * @param ");
             Write(param.Name);
             Write(' ');
             Write(param.Documentation.Summary);
             WriteLine();
         }
     }
     WriteLine(" */");
     }
 }
예제 #37
0
파일: GenCs.cs 프로젝트: haifenghuang/cito
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteName(method);
         WriteArgsInParentheses(method, args);
     }
     else if ((method == CiSystem.StringIndexOf || method == CiSystem.StringLastIndexOf) &&
              IsOneAsciiString(args[0], out char c))
     {
         obj.Accept(this, CiPriority.Primary);
         Write('.');
         Write(method.Name);
         Write('(');
         WriteCharLiteral(c);
         Write(')');
     }
     else if (method == CiSystem.UTF8GetString)
     {
         Include("System.Text");
         Write("Encoding.UTF8.GetString");
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.RegexCompile)
     {
         Include("System.Text.RegularExpressions");
         Write("new Regex");
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.MatchFindStr)
     {
         Include("System.Text.RegularExpressions");
         Write('(');
         obj.Accept(this, CiPriority.Assign);
         Write(" = Regex.Match");
         WriteArgsInParentheses(method, args);
         Write(").Success");
     }
     else if (method == CiSystem.MatchFindRegex)
     {
         Include("System.Text.RegularExpressions");
         Write('(');
         obj.Accept(this, CiPriority.Assign);
         Write(" = ");
         args[1].Accept(this, CiPriority.Primary);
         Write(".Match(");
         args[0].Accept(this, CiPriority.Statement);
         Write(")).Success");
     }
     else if (method == CiSystem.MatchGetCapture)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".Groups[");
         args[0].Accept(this, CiPriority.Statement);
         Write("].Value");
     }
     else if (obj.Type is CiArrayType && !(obj.Type is CiListType) && method.Name == "CopyTo")
     {
         Include("System");
         Write("Array.Copy(");
         obj.Accept(this, CiPriority.Statement);
         Write(", ");
         WriteArgs(method, args);
         Write(')');
     }
     else if (obj.Type is CiArrayStorageType && method.Name == "Fill")
     {
         if (!(args[0] is CiLiteral literal) || !literal.IsDefaultValue)
         {
             throw new NotImplementedException("Only null, zero and false supported");
         }
         Include("System");
         Write("Array.Clear(");
         obj.Accept(this, CiPriority.Statement);
         Write(", 0, ");
         Write(((CiArrayStorageType)obj.Type).Length);
         Write(')');
     }
     else if (WriteListAddInsert(obj, method, args, "Add", "Insert", ", "))
     {
         // done
     }
     else if (obj.Type is CiDictionaryType dict && method.Name == "Add")
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".Add(");
         args[0].Accept(this, CiPriority.Statement);
         Write(", ");
         WriteNewStorage(dict.ValueType);
         Write(')');
     }
예제 #38
0
파일: GenPerl5.cs 프로젝트: epi/cito
	void WriteConstructor(CiClass klass)
	{
		// TODO: skip constructor if static methods only?

		if (klass.Visibility == CiVisibility.Public) {
			Write("=head2 C<$");
			WriteLowercase(klass.Name);
			Write(" = ");
			Write(this.Package);
			Write(klass.Name);
			WriteLine("-E<gt>new()>");
			WriteLine();
			if (klass.Constructor != null)
				Write(klass.Constructor.Documentation);
			WriteLine("=cut");
			WriteLine();
		}

		IEnumerable<CiField> classStorageFields = klass.Members
			.OfType<CiField>().Where(field => field.Type is CiClassStorageType);
		if (klass.Constructor == null && klass.BaseClass != null && !classStorageFields.Any()) {
			// base constructor does the job
			return;
		}

		Write("sub new($) ");
		OpenBlock();
		if (klass.BaseClass != null)
			WriteLine("my $self = shift()->SUPER::new();");
		else
			WriteLine("my $self = bless {}, shift;");
		foreach (CiField field in classStorageFields) {
			Write("$self->{");
			WriteLowercaseWithUnderscores(field.Name);
			Write("} = ");
			WriteNew(field.Type);
			WriteLine(";");
		}
		if (klass.Constructor != null) {
			this.CurrentMethod = klass.Constructor;
			Write(klass.Constructor.Body.Statements);
			this.CurrentMethod = null;
		}
		WriteLine("return $self;"); // TODO: premature returns
		CloseBlock();
		WriteLine();
	}
예제 #39
0
파일: SourceGenerator.cs 프로젝트: epi/cito
 protected virtual void WriteName(CiMethod method)
 {
     Write(method.Name);
 }
예제 #40
0
파일: GenCs.cs 프로젝트: epi/cito
        void ICiSymbolVisitor.Visit(CiMethod method)
        {
            WriteLine();
            Write(method.Documentation);
            foreach (CiParam param in method.Signature.Params) {
            if (param.Documentation != null) {
                Write("/// <param name=\"");
                Write(param.Name);
                Write("\">");
                Write(param.Documentation.Summary);
                WriteLine("</param>");
            }
            }

            Write(method.Visibility);
            switch (method.CallType) {
            case CiCallType.Static: Write("static "); break;
            case CiCallType.Normal: break;
            case CiCallType.Abstract: Write("abstract "); break;
            case CiCallType.Virtual: Write("virtual "); break;
            case CiCallType.Override: Write("override "); break;
            }
            WriteSignature(method.Signature);
            if (method.CallType == CiCallType.Abstract)
            WriteLine(";");
            else {
            WriteLine();
            Write(method.Body);
            }
        }
예제 #41
0
파일: CiResolver.cs 프로젝트: epi/cito
 static void MarkThrows(CiMethod method)
 {
     if (method.Throws)
     return;
     method.Throws = true;
     method.ErrorReturnValue = GetErrorValue(method.Signature.ReturnType);
     foreach (CiMethod calledBy in method.CalledBy)
     MarkThrows(calledBy);
 }
예제 #42
0
파일: GenCpp.cs 프로젝트: jedwards1211/cito
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteName(method);
         WriteArgsInParentheses(method, args);
     }
     else if (obj.IsReferenceTo(CiSystem.MathClass))
     {
         Include("cmath");
         Write("std::");
         WriteMathCall(method, args);
     }
     else if (method == CiSystem.StringContains)
     {
         if (parent > CiPriority.Equality)
         {
             Write('(');
         }
         WriteStringMethod(obj, "find", method, args);
         Write(" != std::string::npos");
         if (parent > CiPriority.Equality)
         {
             Write(')');
         }
     }
     else if (method == CiSystem.StringIndexOf)
     {
         Write("static_cast<int>(");
         WriteStringMethod(obj, "find", method, args);
         Write(')');
     }
     else if (method == CiSystem.StringLastIndexOf)
     {
         Write("static_cast<int>(");
         WriteStringMethod(obj, "rfind", method, args);
         Write(')');
     }
     else if (method == CiSystem.StringStartsWith)
     {
         WriteStringMethod(obj, "starts_with", method, args);
     }
     else if (method == CiSystem.StringEndsWith)
     {
         WriteStringMethod(obj, "ends_with", method, args);
     }
     else if (method == CiSystem.StringSubstring)
     {
         WriteStringMethod(obj, "substr", method, args);
     }
     else if (obj.Type is CiArrayType && method.Name == "CopyTo")
     {
         Include("algorithm");
         Write("std::copy_n(");
         WriteArrayPtrAdd(obj, args[0]);
         Write(", ");
         args[3].Accept(this, CiPriority.Statement);
         Write(", ");
         WriteArrayPtrAdd(args[1], args[2]);
         Write(')');
     }
     else if (obj.Type is CiListType list && method.Name == "Add")
     {
         if (method.Parameters.Count == 0)
         {
             string suffix = ".emplace_back()";
             if (!this.AtLineStart)
             {
                 if (list.ElementType is CiArrayStorageType)
                 {
                     suffix = ".emplace_back().data()";
                 }
                 else
                 {
                     Write('&');
                 }
             }
             obj.Accept(this, CiPriority.Primary);
             Write(suffix);
         }
         else
         {
             obj.Accept(this, CiPriority.Primary);
             Write(".push_back");
             WriteArgsInParentheses(method, args);
         }
     }
예제 #43
0
 protected virtual void WriteName(CiMethod method)
 {
     Write(method.Name);
 }
예제 #44
0
파일: GenJs.cs 프로젝트: epi/cito
 void Write(CiMethod method)
 {
     if (method.CallType == CiCallType.Abstract)
     return;
     WriteLine();
     Write(method.Class.Name);
     Write('.');
     if (method.CallType != CiCallType.Static)
     Write("prototype.");
     WriteCamelCase(method.Name);
     Write(" = function(");
     bool first = true;
     foreach (CiParam param in method.Signature.Params) {
     if (first)
         first = false;
     else
         Write(", ");
     Write(param.Name);
     }
     Write(") ");
     Write(method.Body);
 }
예제 #45
0
파일: GenC.cs 프로젝트: epi/cito
        void WriteConstructorNewDelete(CiClass klass)
        {
            if (klass.Constructs) {
            WriteLine();
            this.CurrentMethod = klass.Constructor;
            WriteConstructorSignature(klass);
            WriteLine();
            OpenBlock();
            if (klass.Constructor != null)
                StartBlock(klass.Constructor.Body.Statements);
            CiClass ptrClass = GetVtblPtrClass(klass);
            if (HasVtblValue(klass)) {
                WriteLine("if (vtbl == NULL)");
                this.Indent++;
                Write("vtbl = ");
                CiClass structClass = GetVtblStructClass(klass);
                if (structClass != ptrClass) {
                    Write("(const ");
                    Write(ptrClass.Name);
                    Write("Vtbl *) ");
                }
                Write("&CiVtbl_");
                Write(klass.Name);
                WriteLine(";");
                this.Indent--;
            }
            if (ptrClass == klass)
                WriteLine("self->vtbl = vtbl;");
            if (klass.BaseClass != null && klass.BaseClass.Constructs) {
                Write(klass.BaseClass.Name);
                Write("_Construct(&self->base");
                if (HasVirtualMethods(klass.BaseClass))
                    Write(", vtbl");
                WriteLine(");");
            }
            ForEachStorageField(klass, (field, fieldClass) => {
                if (fieldClass.Constructs) {
                    Write(fieldClass.Name);
                    Write("_Construct(&self->");
                    WriteCamelCase(field.Name);
                    if (HasVirtualMethods(fieldClass))
                        Write(", NULL");
                    WriteLine(");");
                }
            });
            if (klass.Constructor != null)
                Write(klass.Constructor.Body.Statements);
            CloseBlock();
            this.CurrentMethod = null;
            }
            if (!klass.IsAbstract && HasCStruct(klass)) {
            if (klass.Visibility == CiVisibility.Public) {
                WriteLine();
                WriteNew(klass);

                WriteLine();
                WriteDeleteSignature(klass);
                WriteLine();
                OpenBlock();
                WriteLine("free(self);");
                CloseBlock();
            }
            else if (klass.IsAllocated) {
                WriteLine();
                Write("static ");
                WriteNew(klass);
            }
            }
        }
예제 #46
0
파일: GenAs.cs 프로젝트: epi/cito
 void ICiSymbolVisitor.Visit(CiMethod method)
 {
     WriteLine();
     WriteDoc(method);
     WriteVisibility(method);
     switch (method.CallType) {
     case CiCallType.Static: Write("static "); break;
     case CiCallType.Normal: if (method.Visibility != CiVisibility.Private) Write("final "); break;
     case CiCallType.Override: Write("override "); break;
     default: break;
     }
     Write("function ");
     WriteCamelCase(method.Name);
     Write('(');
     bool first = true;
     foreach (CiParam param in method.Signature.Params) {
     if (first)
         first = false;
     else
         Write(", ");
     Write(param.Name);
     Write(param.Type);
     }
     Write(")");
     Write(method.Signature.ReturnType);
     WriteLine();
     OpenBlock();
     if (method.CallType == CiCallType.Abstract)
     WriteLine("throw \"Abstract method called\";");
     else {
     ICiStatement[] statements = method.Body.Statements;
     Write(statements);
     if (method.Signature.ReturnType != CiType.Void && statements.Length > 0) {
         CiFor lastLoop = statements[statements.Length - 1] as CiFor;
         if (lastLoop != null && lastLoop.Cond == null)
             WriteLine("throw \"Unreachable\";");
     }
     }
     CloseBlock();
 }
예제 #47
0
 protected override void WriteCall(CiExpr obj, CiMethod method, CiExpr[] args, CiPriority parent)
 {
     if (obj == null)
     {
         WriteName(method);
         WriteArgsInParentheses(method, args);
     }
     else if ((method == CiSystem.StringIndexOf || method == CiSystem.StringLastIndexOf) &&
              IsOneAsciiString(args[0], out char c))
     {
         obj.Accept(this, CiPriority.Primary);
         Write('.');
         Write(method.Name);
         Write('(');
         WriteCharLiteral(c);
         Write(')');
     }
     else if (method == CiSystem.UTF8GetString)
     {
         Include("System.Text");
         Write("Encoding.UTF8.GetString");
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.RegexCompile)
     {
         Include("System.Text.RegularExpressions");
         Write("new Regex");
         WriteArgsInParentheses(method, args);
     }
     else if (method == CiSystem.MatchFindStr)
     {
         Include("System.Text.RegularExpressions");
         Write('(');
         obj.Accept(this, CiPriority.Assign);
         Write(" = Regex.Match");
         WriteArgsInParentheses(method, args);
         Write(").Success");
     }
     else if (method == CiSystem.MatchFindRegex)
     {
         Include("System.Text.RegularExpressions");
         Write('(');
         obj.Accept(this, CiPriority.Assign);
         Write(" = ");
         WriteCall(args[1], "Match", args[0]);
         Write(").Success");
     }
     else if (method == CiSystem.MatchGetCapture)
     {
         obj.Accept(this, CiPriority.Primary);
         Write(".Groups[");
         args[0].Accept(this, CiPriority.Statement);
         Write("].Value");
     }
     else if (obj.Type is CiArrayType array && method.Name == "BinarySearch")
     {
         Include("System");
         Write("Array.BinarySearch(");
         obj.Accept(this, CiPriority.Statement);
         Write(", ");
         if (args.Length == 3)
         {
             args[1].Accept(this, CiPriority.Statement);
             Write(", ");
             args[2].Accept(this, CiPriority.Statement);
             Write(", ");
         }
         WriteNotPromoted(array.ElementType, args[0]);
         Write(')');
     }
예제 #48
0
파일: GenC.cs 프로젝트: epi/cito
 void WritePtr(CiMethod method, string name)
 {
     StringBuilder sb = new StringBuilder();
     sb.Append("(*");
     sb.Append(name);
     sb.Append(")(");
     sb.Append(method.Class.Name);
     sb.Append(" *self");
     foreach (CiParam param in method.Signature.Params) {
     sb.Append(", ");
     sb.Append(ToString(param.Type, param.Name));
     }
     sb.Append(')');
     CiType type = method.Signature.ReturnType;
     if (method.Throws && type == CiType.Void) // TODO: check subclasses
     type = CiBoolType.Value;
     Write(type, sb.ToString());
 }
예제 #49
0
파일: CiResolver.cs 프로젝트: epi/cito
 static void MarkInternal(CiMethod method)
 {
     if (method.Visibility == CiVisibility.Private && method.CalledBy.Any(caller => caller.Class != method.Class))
     method.Visibility = CiVisibility.Internal;
 }
예제 #50
0
파일: GenJava.cs 프로젝트: epi/cito
 void ICiSymbolVisitor.Visit(CiMethod method)
 {
     WriteLine();
     WriteDoc(method);
     if (method.CallType == CiCallType.Override)
     WriteLine("@Override");
     Write(method.Visibility);
     switch (method.CallType) {
     case CiCallType.Static: Write("static "); break;
     case CiCallType.Normal: if (method.Visibility != CiVisibility.Private) Write("final "); break;
     case CiCallType.Abstract: Write("abstract "); break;
     default: break;
     }
     WriteSignature(method.Signature, method.Name);
     if (method.Throws)
     Write(" throws Exception");
     if (method.CallType == CiCallType.Abstract)
     WriteLine(";");
     else {
     WriteLine();
     Write(method.Body);
     }
 }
예제 #51
0
 protected void WriteArgsInParentheses(CiMethod method, CiExpr[] args)
 {
     Write('(');
     WriteArgs(method, args);
     Write(')');
 }