From e1019d478e06d6bc5cf04bcb2c4fe29433a118df Mon Sep 17 00:00:00 2001 From: zdimension Date: Tue, 20 Oct 2015 03:20:10 +0200 Subject: [PATCH] Fixed tuples, added lambda and func support to 'is' operator and added ssl + credentials support to the smtp class --- src/Hassium/HassiumObjects/HassiumObject.cs | 3 +- src/Hassium/HassiumObjects/HassiumTuple.cs | 27 +++++++++--- .../Networking/Mail/HassiumSmtpClient.cs | 43 ++++++++++++++++++- src/Hassium/Interpreter/HassiumMethod.cs | 18 +++++--- src/Hassium/Interpreter/Interpreter.cs | 31 ++++++++++++- src/Hassium/Parser/Parser.cs | 10 +++-- 6 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/Hassium/HassiumObjects/HassiumObject.cs b/src/Hassium/HassiumObjects/HassiumObject.cs index fc0b20b..562c284 100644 --- a/src/Hassium/HassiumObjects/HassiumObject.cs +++ b/src/Hassium/HassiumObjects/HassiumObject.cs @@ -39,7 +39,7 @@ namespace Hassium.HassiumObjects public class HassiumObject : IFunction { - private readonly Dictionary _attributes; + private Dictionary _attributes; public bool IsInstance { get; set; } @@ -50,6 +50,7 @@ public class HassiumObject : IFunction public Dictionary Attributes { get { return _attributes; } + protected set { _attributes = value; } } public HassiumObject() diff --git a/src/Hassium/HassiumObjects/HassiumTuple.cs b/src/Hassium/HassiumObjects/HassiumTuple.cs index 0356b89..260c2d4 100644 --- a/src/Hassium/HassiumObjects/HassiumTuple.cs +++ b/src/Hassium/HassiumObjects/HassiumTuple.cs @@ -41,34 +41,47 @@ public class HassiumTuple: HassiumObject private int position { get; set; } - + public List Items { get; private set; } public HassiumTuple(TupleNode value, Hassium.Interpreter.Interpreter interpreter) : this(value.Children[0].Children.Select((v, i) => (HassiumObject)v.Visit(interpreter)).ToList(), interpreter) { TupleNode = value; } + + public HassiumTuple(IList value, Hassium.Interpreter.Interpreter interpreter) { - for (position = 0; position < value.Count; position++) - Attributes.Add("Item" + position, value[position]); + Items = value.ToList(); + + refresh(); Attributes.Add("add", new InternalFunction(add, -1)); Attributes.Add("remove", new InternalFunction(remove, -1)); } + + private void refresh() + { + Attributes = + Items.Select((item, index) => new KeyValuePair("Item" + index, item)) + .ToDictionary(x => x.Key, x => x.Value); + } + private HassiumObject add(HassiumObject[] args) { - foreach (HassiumObject arg in args) - Attributes.Add("Item" + position++, arg); + Items.AddRange(args); + + refresh(); return null; } private HassiumObject remove(HassiumObject[] args) { - foreach (HassiumObject arg in args) - Attributes.Remove(((HassiumString)arg).Value); + args.All(x => Items.Remove(x)); + + refresh(); return null; } diff --git a/src/Hassium/HassiumObjects/Networking/Mail/HassiumSmtpClient.cs b/src/Hassium/HassiumObjects/Networking/Mail/HassiumSmtpClient.cs index f8f5970..06ae8cb 100644 --- a/src/Hassium/HassiumObjects/Networking/Mail/HassiumSmtpClient.cs +++ b/src/Hassium/HassiumObjects/Networking/Mail/HassiumSmtpClient.cs @@ -27,6 +27,8 @@ using System.Collections.Generic; using System.Net.Mail; using System.Linq; +using System.Net; +using System.Runtime.Remoting.Metadata.W3cXsd2001; using System.Text; using Hassium.Interpreter; using Hassium.Functions; @@ -41,7 +43,46 @@ public class HassiumSmtpClient: HassiumObject public HassiumSmtpClient(HassiumString server, HassiumInt port) { Value = new SmtpClient(server.ToString(), port.Value); - Attributes.Add("send", new InternalFunction(send, new int[] { 1, 4 })); + Attributes.Add("send", new InternalFunction(send, new int[] {1, 4})); + + Attributes.Add("credentials", new HassiumProperty("credentials", + x => + { + var cred = new HassiumObject(); + cred.Attributes.Add("username", + new HassiumProperty("username", y => (Value.Credentials as NetworkCredential).UserName, + (self, y) => + { + Value.Credentials = + new NetworkCredential(y[0].ToString(), + (Value.Credentials as NetworkCredential).Password); + return null; + })); + cred.Attributes.Add("password", + new HassiumProperty("password", y => (Value.Credentials as NetworkCredential).Password, + (self, y) => + { + Value.Credentials = + new NetworkCredential((Value.Credentials as NetworkCredential).UserName, + y[0].ToString()); + return null; + })); + + return cred; + }, + (self, y) => + { + if(y[0] is HassiumTuple) + { + var tuple = (HassiumTuple) y[0]; + Value.Credentials = new NetworkCredential(tuple.Items[0].ToString(), tuple.Items[1].ToString()); + } + + return null; + })); + + Attributes.Add("enableSsl", + new HassiumProperty("enableSsl", x => Value.EnableSsl, (self, x) => Value.EnableSsl = x[0].HBool())); } private HassiumObject send(HassiumObject[] args) diff --git a/src/Hassium/Interpreter/HassiumMethod.cs b/src/Hassium/Interpreter/HassiumMethod.cs index de01117..b527447 100644 --- a/src/Hassium/Interpreter/HassiumMethod.cs +++ b/src/Hassium/Interpreter/HassiumMethod.cs @@ -46,6 +46,8 @@ public string Name get { return FuncNode.Name; } } + public bool IsLambda { get; private set; } + public bool IsStatic { get { return !FuncNode.Parameters.Contains("this"); } @@ -57,22 +59,25 @@ public bool IsConstructor get { return Name == "new"; } } - public HassiumMethod(Interpreter interpreter, FuncNode funcNode, LocalScope localScope, HassiumObject self) + public HassiumMethod(Interpreter interpreter, FuncNode funcNode, LocalScope localScope, HassiumObject self, bool lambda = false) : this(interpreter, funcNode, (StackFrame)null, self, lambda) { - SelfReference = self; + /*SelfReference = self; Interpreter = interpreter; FuncNode = funcNode; LocalScope = localScope; stackFrame = null; + IsLambda = lambda;*/ + LocalScope = localScope; } - public HassiumMethod(Interpreter interpreter, FuncNode funcNode, StackFrame stackFrame, HassiumObject self) + public HassiumMethod(Interpreter interpreter, FuncNode funcNode, StackFrame stackFrame, HassiumObject self, bool lambda = false) { SelfReference = self; Interpreter = interpreter; FuncNode = funcNode; LocalScope = stackFrame == null ? null : stackFrame.Scope; this.stackFrame = stackFrame; + IsLambda = lambda; } public static implicit operator HassiumEventHandler(HassiumMethod mt) @@ -95,7 +100,8 @@ public override HassiumObject Invoke(params HassiumObject[] args) if (parms.Contains("this")) parms.Remove("this"); if (parms.Count != args.Length) - throw new Exception("Incorrect arguments for function " + Name + ": Expected " + parms.Count + " args, got " + args.Length); + throw new Exception("Incorrect arguments for " + + (IsLambda ? "lambda function" : "function " + Name ) + ": Expected " + parms.Count + " args, got " + args.Length); for (int x = 0; x < parms.Count; x++) stackFrame.Locals[parms[x]] = args[x]; @@ -120,8 +126,8 @@ public override HassiumObject Invoke(params HassiumObject[] args) public override string ToString() { - return string.Format("[HassiumMethod: {0}`{1} SelfReference={2}]", Name, (FuncNode.InfParams ? "i" : FuncNode.Parameters.Count.ToString()), - SelfReference ?? "null"); + return string.Format("[HassiumMethod: {0}`{1} SelfReference={2} {3}]", Name, (FuncNode.InfParams ? "i" : FuncNode.Parameters.Count.ToString()), + SelfReference ?? "null", IsLambda ? "Lambda" : ""); } /// diff --git a/src/Hassium/Interpreter/Interpreter.cs b/src/Hassium/Interpreter/Interpreter.cs index f427f2a..fead74d 100644 --- a/src/Hassium/Interpreter/Interpreter.cs +++ b/src/Hassium/Interpreter/Interpreter.cs @@ -33,6 +33,7 @@ using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using System.Threading; using Hassium.Functions; @@ -293,6 +294,30 @@ private HassiumObject interpretBinaryOp(BinOpNode node) if(node.Right is IdentifierNode) { var name = node.Right.ToString().ToLower(); + if (name.Contains("`")) + { + var n = name.Split('`')[0]; + var pnums = name.Split('`')[1]; + if (pnums == "") + { + throw new ParseException("Expected argument number", node.Right.Position + n.Length + 1); + } + var pnum = -1; + try + { + pnum = int.Parse(pnums); + } + catch + { + throw new ParseException("Invalid argument number: " + pnums, + node.Right.Position + n.Length + 1); + } + return target is HassiumMethod && + (n == "lambda" + ? ((HassiumMethod) target).IsLambda + : n == "func" && !((HassiumMethod) target).IsLambda) && + ((HassiumMethod) target).FuncNode.Parameters.Count == pnum; + } switch (name) { case "string": @@ -324,6 +349,10 @@ private HassiumObject interpretBinaryOp(BinOpNode node) return true; case "tuple": return target is HassiumTuple; + case "func": + return target is HassiumMethod && !((HassiumMethod)target).IsLambda; + case "lambda": + return target is HassiumMethod && ((HassiumMethod) target).IsLambda; } } else @@ -1367,7 +1396,7 @@ public object Accept(LambdaFuncNode node) return true; }); } - return new HassiumMethod(this, (FuncNode) funcNode, stackFrame, null); + return new HassiumMethod(this, (FuncNode) funcNode, stackFrame, null, true); } public object Accept(MemberAccessNode node) diff --git a/src/Hassium/Parser/Parser.cs b/src/Hassium/Parser/Parser.cs index 1f10580..4e5d9ca 100644 --- a/src/Hassium/Parser/Parser.cs +++ b/src/Hassium/Parser/Parser.cs @@ -1171,12 +1171,16 @@ private static AstNode ParseTerm(Parser parser) switch (curt.Value.ToString()) { case "lambda": - return parseLambda(parser); + return parser.PreviousToken(-1).TokenClass != TokenType.LParen + ? new IdentifierNode(position, parser.ExpectToken(TokenType.Identifier).Value.ToString()) + : parseLambda(parser); case "new": return ParseInstance(parser); case "tuple": - if(parser.PreviousToken(-1).TokenClass == TokenType.LParen - || (parser.PreviousToken(-1).TokenClass == TokenType.Identifier && parser.PreviousToken(-2).TokenClass == TokenType.LParen)) return parseTuple(parser); + if (parser.PreviousToken(-1).TokenClass == TokenType.LParen + || + (parser.PreviousToken(-1).TokenClass == TokenType.Identifier && + parser.PreviousToken(-2).TokenClass == TokenType.LParen)) return parseTuple(parser); break; } return new IdentifierNode(position, parser.ExpectToken(TokenType.Identifier).Value.ToString());