using System.Collections.Generic; using System.Linq; namespace arookas { class sunBuiltinDeclaration : sunNode { public sunIdentifier Builtin { get { return this[0] as sunIdentifier; } } public sunParameterList Parameters { get { return this[1] as sunParameterList; } } public sunBuiltinDeclaration(sunSourceLocation location) : base(location) { } public override void Compile(sunContext context) { context.DeclareBuiltin(this); } } class sunFunctionDefinition : sunNode { public sunIdentifier Function { get { return this[0] as sunIdentifier; } } public sunParameterList Parameters { get { return this[1] as sunParameterList; } } public sunNode Body { get { return this[2]; } } public sunFunctionDefinition(sunSourceLocation location) : base(location) { } public override void Compile(sunContext context) { context.DefineFunction(this); // possibly counter intuitively, this defines the function in the context; it doesn't compile the definition body } } class sunFunctionCall : sunNode { public sunIdentifier Function { get { return this[0] as sunIdentifier; } } public sunNode Arguments { get { return this[1] as sunNode; } } bool IsStatement { get { return !(Parent is sunOperand); } } public sunFunctionCall(sunSourceLocation location) : base(location) { } public override void Compile(sunContext context) { var callableInfo = context.ResolveCallable(this); if (!callableInfo.Parameters.ValidateArgumentCount(Arguments.Count)) { throw new sunArgumentCountException(this, callableInfo); } Arguments.Compile(context); callableInfo.OpenCallSite(context, Arguments.Count); if (IsStatement) { context.Text.Pop(); } } } class sunParameterList : sunNode { public IEnumerable Parameters { get { return this.OfType(); } } public bool IsVariadic { get { return Count > 0 && this[Count - 1] is sunEllipsis; } } public sunParameterInfo ParameterInfo { get { return new sunParameterInfo(Parameters, IsVariadic); } } public sunParameterList(sunSourceLocation location) : base(location) { int count = this.Count(i => i is sunEllipsis); if (count > 1 || (count > 0 && !(this[Count - 1] is sunEllipsis))) { throw new sunVariadicParameterListException(this); } } } class sunEllipsis : sunNode { public sunEllipsis(sunSourceLocation location) : base(location) { } } }