Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Console.WriteLine("------ Basic examples -------")
      uc.Define("Function: f(x, y) = x + y")
      uc.Define("Operator: {x} %% {y} = x * y")
      uc.Define("Variable: MyVar = 123")
      
      Console.WriteLine(uc.Eval("f(5, 10)"))
      Console.WriteLine(uc.Eval("5 %% 10"))
      Console.WriteLine(uc.Eval("MyVar * 100"))
      
      '// End users can also call Define()
      Console.WriteLine("------ End user definition -------")
      uc.Eval("Define('Function: ff(x) = x * 1000')")
      Console.WriteLine(uc.Eval("ff(987)"))
      
      Console.WriteLine("------ Boolean format -------")
      Console.WriteLine(uc.EvalStr("1 < 2"))
      Console.WriteLine(uc.EvalStr("1 > 2"))
      Console.WriteLine(uc.EvalStr("Int(1 < 2)"))
      Console.WriteLine(uc.EvalStr("(True Or False) And (True And False)"))
      uc.Define("Boolean: 55, TotallyTrue, CompletelyFalse")
      Console.WriteLine(uc.EvalStr("1 < 2"))
      Console.WriteLine(uc.EvalStr("1 > 2"))
      Console.WriteLine(uc.EvalStr("Int(1 < 2)"))
      Console.WriteLine(uc.EvalStr("(TotallyTrue Or CompletelyFalse) And (TotallyTrue And CompletelyFalse)"))
      
      '// Format - configures the formatting for the output given by EvalStr
      Console.WriteLine("------ Format -------")
      uc.Define("Format: Result = 'Answer: <' + Result + '>'")
      uc.Define("Format: String, val = 'String Value --> ' + val")
      Console.WriteLine(uc.EvalStr("1+2"))
      Console.WriteLine(uc.EvalStr("'Hello ' + 'world!'"))
      Dim Additional = uc.Define("Format: ret = 'Additional format: ' + ret")
      Console.WriteLine(uc.EvalStr("1+2"))
      uc.Define("Format: InsertAt: 0, result = 'The ' + result")
      Console.WriteLine(uc.EvalStr("1+2"))
      Additional.Release()
      Console.WriteLine(uc.EvalStr("1+2"))
      uc.FormatRemove()
      
      '// Bootstrap - builds new def on top of existing one
      Console.WriteLine("------ Bootstrap -------")
      Console.WriteLine(uc.EvalStr("Hex(123)")) '// uses "built-in" version of Hex()
      Dim MyHex = uc.Define("Bootstrap ~~ Function: Hex(number As Int) As String = '0x' + UCase(Hex(number))")
      Console.WriteLine(uc.EvalStr("Hex(123)"))
      MyHex.Release()
      Console.WriteLine(uc.EvalStr("Hex(123)"))
      
      '// Overwrite - useful for spreadsheet-like functionality
      Console.WriteLine("------ Overwrite -------")
      uc.Define("Overwrite ~~ Func: SpreadsheetCell_A1() = 5")
      uc.Define("Overwrite ~~ Func: SpreadsheetCell_B2() = SpreadsheetCell_A1() * 10")
      uc.Define("Overwrite ~~ Func: SpreadsheetCell_C3() = SpreadsheetCell_A1() + SpreadsheetCell_B2()")
      Console.WriteLine(uc.Eval("SpreadsheetCell_A1()"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_B2()"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_C3()"))
      '// SpreadsheetCell_C3() will be affected by the definition changes of SpreadsheetCell_A1() and  SpreadsheetCell_B3()
      uc.Define("Overwrite ~~ Func: SpreadsheetCell_B2() = SpreadsheetCell_A1() * 100")
      uc.Define("Overwrite ~~ Func: SpreadsheetCell_A1() = 25")
      Console.WriteLine("-------")
      '// Note: Empty parenthesis are optional for functions with no parameters
      Console.WriteLine(uc.Eval("SpreadsheetCell_A1"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_B2"))
      Console.WriteLine(uc.Eval("SpreadsheetCell_C3"))
      
      '// Lock
      Console.WriteLine("------ Lock -------")
      uc.Define("Variable: xy = 555")
      uc.Define("Lock ~~ Variable: pi = 3.14") '// like using DefineConstant()
      Console.WriteLine(uc.EvalStr("xy"))
      Console.WriteLine(uc.EvalStr("pi"))
      Console.WriteLine(uc.EvalStr("xy = 222")) '// This variable is being changed
      Console.WriteLine(uc.EvalStr("pi = 3.14159")) '// This one is locked and cannot be changed
      Console.WriteLine(uc.EvalStr("xy")) '// Returns the new value of xy
      Console.WriteLine(uc.EvalStr("pi")) '// pi did not change; returns original value
      Console.WriteLine("-------")
      uc.Define("Function: f1(x) = x + 100")
      uc.Define("Lock ~~ Function: f2(x) = x + 200") '// End-user can't change f2
      Console.WriteLine(uc.Eval("f1(5)"))
      Console.WriteLine(uc.Eval("f2(5)"))
      uc.Eval("Define('Function: f1(x) = x + 300')")
      uc.Eval("Define('Function: f2(x) = x + 400')") '// This re-definition is ignored
      Console.WriteLine(uc.Eval("f1(5)"))
      Console.WriteLine(uc.Eval("f2(5)"))
      
      '// Tokens
      Console.WriteLine("------ Tokens -------")
      Console.WriteLine(uc.EvalStr("5 + 4 // This comment causes an error"))
      Console.WriteLine(uc.EvalStr("5 + /* comment not recognized yet */ 10"))
      uc.Define("TokenType: Whitespace ~~ Token: //.*") '// // C-style to end-of-line comment 
      uc.Define("TokenType: Whitespace ~~ Token: /[*].*?[*]/") '// /* C-style enclosed comment */
      Console.WriteLine(uc.EvalStr("5 + 4 // This comment will be ignored"))
      Console.WriteLine(uc.EvalStr("5 + /* comment ignored */ 10"))
      
      '// Precedence
      Console.WriteLine("------ Precedence -------")
      uc.Define("Precedence: 1    ~~ Operator: {a As Int32} OpA {b As Int32} = a + b")
      uc.Define("Precedence: 1000 ~~ Operator: {a As Int32} OpB {b As Int32} = a + b")
      Console.WriteLine(uc.Eval("5 OpA 4 * 10"))
      Console.WriteLine(uc.Eval("5 OpB 4 * 10"))
      
      '// Associativity
      Console.WriteLine("------ Associativity -------")
      uc.Define("Associativity: LeftToRight ~~ Operator: {x} OpX {y} = x / y")
      uc.Define("Associativity: RightToLeft ~~ Operator: {x} OpY {y} = x / y")
      Console.WriteLine(uc.Eval("3 OpX 4 OpX 5"))
      Console.WriteLine(uc.Eval("3 OpY 4 OpY 5"))
   End Sub
End Module