/// <summary> /// Open a file for input. /// </summary> /// <param name="filename">The filename of the file to open.</param> /// <param name="interp">The interpreter.</param> /// <returns>The input port, used for reading.</returns> internal static InputPort OpenInputFile(SchemeObject filename, Interpreter interp) { try { return InputPort.New(new StreamReader(filename.ToString(false)), interp); } catch (FileNotFoundException) { return (InputPort)ErrorHandlers.IoError("No such file: " + filename.ToString(true)); } catch (IOException ex) { return (InputPort)ErrorHandlers.IoError("IOException: " + ex.Message); } }
/// <summary> /// Write a character on a given port. /// The output is not quoted. /// If the expr is not actually a character, it is written nevertheless. /// </summary> /// <param name="expr">The expression to write.</param> /// <returns>The undefined object.</returns> private SchemeObject WriteChar(SchemeObject expr) { this.Write(expr.ToString(false)); return Undefined.Instance; }
/// <summary> /// Print the obj on the console. /// </summary> /// <param name="x">The obj to print.</param> /// <returns>Undefined value.</returns> private SchemeObject P(SchemeObject x) { this.WriteLine(x.ToString(false)); return Undefined.Instance; }
/// <summary> /// Create a printable representation of the object. /// </summary> /// <param name="obj">The object to print.</param> /// <returns>The string representing the object.</returns> public string Print(SchemeObject obj) { try { return obj.ToString(true); } catch (Exception ex) { ErrorHandlers.PrintException(ex); return string.Empty; } }
/// <summary> /// Load a file. /// Open the file and read it. /// Evaluate whatever it contains. /// This may be one or more expressions. /// If any of them are asynchronous, then the evaluation is NOT blocked, but continues on. /// </summary> /// <param name="fileName">The filename.</param> /// <param name="outp">If not null, input and results are written here.</param> public void LoadFile(SchemeObject fileName, OutputPort outp) { string name = string.Empty; try { name = fileName.ToString(); using (var fs = new FileStream(name, FileMode.Open, FileAccess.Read)) { this.Load(InputPort.New(new StreamReader(fs), this), outp); } } catch (IOException) { ErrorHandlers.IoError("Can't load " + name); } }
/// <summary> /// Get an individual counter value. /// </summary> /// <param name="name">The counter name.</param> /// <returns>The counter value.</returns> private SchemeObject GetCounter(SchemeObject name) { string counterName = name.ToString(); lock (this) { foreach (var kvp in this.counters) { if (kvp.Key == counterName) { return (Number)kvp.Value; } } } return Undefined.Instance; }
/// <summary> /// Add or update a symbol table entry at this level. /// </summary> /// <param name="symbol">The symbol to update.</param> /// <param name="val">The new value.</param> internal void Update(SchemeObject symbol, SchemeObject val) { if (!(symbol is Symbol)) { ErrorHandlers.SemanticError(string.Format(@"Attempt to update a non-symbol: ""{0}""", symbol.ToString(true)), symbol); } this.symbolTable.Add((Symbol)symbol, val); }
/// <summary> /// Increment the variable. /// </summary> /// <param name="var">The symbol naming the variable to increment.</param> /// <returns>The incremented value.</returns> internal SchemeObject Increment(SchemeObject var) { if (!(var is Symbol)) { return ErrorHandlers.SemanticError(string.Format(@"Attempt to increment a non-symbol: ""{0}""", var.ToString(true)), var); } var symbol = (Symbol)var; Environment env = this; // search down the chain of environments for a definition while (env != emptyEnvironment) { SchemeObject val = env.symbolTable.Increment(symbol); if (val != null) { return val; } // if we have not found anything yet, look in the parent env = env.lexicalParent; } return ErrorHandlers.SemanticError(string.Format(@"Unbound variable in set!: ""{0}""", symbol.SymbolName), symbol); }
/// <summary> /// Turn on transcripts, writing to the given file. /// </summary> /// <param name="fileName">The file to write to.</param> internal void TranscriptOn(SchemeObject fileName) { if (this.transcriptWriter != null) { this.transcriptWriter.Close(); } string name = fileName.ToString(false); this.transcriptWriter = new StreamWriter(new FileStream(name, FileMode.Create, FileAccess.Write)); }
/// <summary> /// Check one of the arguments /// </summary> /// <param name="arg">An argument passed to the primitive.</param> /// <param name="argType">The expected argument type.</param> private void CheckArgType(SchemeObject arg, ArgType argType) { if (ArgTypeTester.Ok(arg, argType)) { return; } var msg = string.Format( @"Primitive ""{0}"" invalid argument ""{1}"". Got type: {2}. Expected type: {3}", this.ProcedureName, arg.ToString(true), arg.GetType().Name, ArgTypeTester.ValueMessage(argType)); ErrorHandlers.SemanticError(msg, arg); }
/// <summary> /// Set the RestCell member of a pair destructively. /// </summary> /// <param name="pair">The pair whose RestCell we want to modify.</param> /// <param name="newTail">The new value to put into it.</param> /// <returns>Undefined instance.</returns> public static SchemeObject SetRest(SchemeObject pair, SchemeObject newTail) { if (pair is Pair) { ((Pair)pair).SetRest(newTail); return Undefined.Instance; } return ErrorHandlers.SemanticError(string.Format(@"Attempt to set-cdr! of a non-Pair: ""{0}""", pair.ToString(true)), pair); }