From 5e538288d29e0a4b696ca1d8d2a6564dd25e986b Mon Sep 17 00:00:00 2001 From: Will Speak Date: Sat, 22 Jun 2024 10:05:48 +0100 Subject: [PATCH] `.editorconfig` Improvements Update code style for C#, and codify it in the eidtor config file. --- .editorconfig | 13 + src/Serehfa/ArgHelpers.cs | 105 +++--- src/Serehfa/Arithmetics.cs | 226 ++++++------- src/Serehfa/Attributes/LispExportAttribute.cs | 29 +- .../Attributes/LispLibraryAttribute.cs | 29 +- .../Attributes/LispReExportAttribute.cs | 45 ++- src/Serehfa/Booleans.cs | 49 ++- src/Serehfa/ByteVectors.cs | 142 ++++----- src/Serehfa/Characters.cs | 298 +++++++++--------- src/Serehfa/ConsPair.cs | 63 ++-- src/Serehfa/Core.cs | 34 +- src/Serehfa/Equivalence.cs | 182 +++++------ src/Serehfa/Ident.cs | 99 +++--- src/Serehfa/Lists.cs | 197 ++++++------ src/Serehfa/ProcessContext.cs | 112 +++---- src/Serehfa/RandomBits.cs | 41 +-- src/Serehfa/Read.cs | 150 ++++----- src/Serehfa/Strings.cs | 76 ++--- src/Serehfa/Symbols.cs | 59 ++-- src/Serehfa/Time.cs | 54 ++-- src/Serehfa/Undefined.cs | 43 ++- src/Serehfa/Vectors.cs | 134 ++++---- src/Serehfa/Write.cs | 177 +++++------ 23 files changed, 1186 insertions(+), 1171 deletions(-) diff --git a/.editorconfig b/.editorconfig index db7b539f..cfa8f123 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,6 +15,19 @@ indent_style = space [*.cs] indent_style = space indent_size = 4 +dotnet_separate_import_directive_groups = true +dotnet_sort_system_directives_first = true +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true +dotnet_style_require_accessibility_modifiers = for_non_interface_members +dotnet_style_operator_placement_when_wrapping = end_of_line +dotnet_style_allow_multiple_blank_lines_experimental = true +dotnet_style_allow_statement_immediately_after_block_experimental = false +csharp_style_namespace_declarations = file_scoped [*.json] indent_style = space diff --git a/src/Serehfa/ArgHelpers.cs b/src/Serehfa/ArgHelpers.cs index 6a1a9d25..35495b1b 100644 --- a/src/Serehfa/ArgHelpers.cs +++ b/src/Serehfa/ArgHelpers.cs @@ -1,76 +1,75 @@ using System; -namespace Serehfa +namespace Serehfa; + +public class ArgHelpers { - public class ArgHelpers + public static void CheckNoArgs(object[] args) { - public static void CheckNoArgs(object[] args) + if (args.Length != 0) { - if (args.Length != 0) - { - throw new ArgumentException( - $"Expected no arguments, but received {args.Length}", - nameof(args)); - } + throw new ArgumentException( + $"Expected no arguments, but received {args.Length}", + nameof(args)); } + } - public static void CheckAtLeastArgs(object[] args, int count) + public static void CheckAtLeastArgs(object[] args, int count) + { + if (args.Length < count) { - if (args.Length < count) - { - throw new ArgumentException( - $"Expected at least {count} arguments, but received {args.Length}", - nameof(args)); - } + throw new ArgumentException( + $"Expected at least {count} arguments, but received {args.Length}", + nameof(args)); } + } - public static T UnpackArgs(object[] args) + public static T UnpackArgs(object[] args) + { + if (args.Length != 1) { - if (args.Length != 1) - { - throw new ArgumentException( - $"Expected 1 arg, but found {args.Length}", - nameof(args)); - } - - return Unpack(args[0]); + throw new ArgumentException( + $"Expected 1 arg, but found {args.Length}", + nameof(args)); } - public static (T, U) UnpackArgs(object[] args) - { - if (args.Length != 2) - { - throw new ArgumentException( - $"Expected 2 args, but found {args.Length}", - nameof(args)); - } + return Unpack(args[0]); + } - return (Unpack(args[0]), Unpack(args[1])); + public static (T, U) UnpackArgs(object[] args) + { + if (args.Length != 2) + { + throw new ArgumentException( + $"Expected 2 args, but found {args.Length}", + nameof(args)); } - public static (T, U, V) UnpackArgs(object[] args) - { - if (args.Length != 3) - { - throw new ArgumentException( - $"Expected 3 args, but found {args.Length}", - nameof(args)); - } + return (Unpack(args[0]), Unpack(args[1])); + } - return (Unpack(args[0]), Unpack(args[1]), Unpack(args[2])); + public static (T, U, V) UnpackArgs(object[] args) + { + if (args.Length != 3) + { + throw new ArgumentException( + $"Expected 3 args, but found {args.Length}", + nameof(args)); } - public static T Unpack(object arg) + return (Unpack(args[0]), Unpack(args[1]), Unpack(args[2])); + } + + public static T Unpack(object arg) + { + if (arg is null) + { + return default; + } + if (arg is T converted) { - if (arg is null) - { - return default; - } - if (arg is T converted) - { - return converted; - } - throw new ArgumentException($"Expected {typeof(T)}, but found {arg?.GetType()}"); + return converted; } + throw new ArgumentException($"Expected {typeof(T)}, but found {arg?.GetType()}"); } } diff --git a/src/Serehfa/Arithmetics.cs b/src/Serehfa/Arithmetics.cs index abdd08fb..ad2b618f 100644 --- a/src/Serehfa/Arithmetics.cs +++ b/src/Serehfa/Arithmetics.cs @@ -1,144 +1,144 @@ using System; using System.Runtime.CompilerServices; + using Serehfa.Attributes; -namespace Serehfa +namespace Serehfa; + +using static ArgHelpers; + +[LispLibrary("feersum", "serehfa", "arithmetics")] +public static class Arithmetics { - using static ArgHelpers; + [LispExport("zero?")] + public static object ArithZero(object[] args) + { + return UnpackArgs(args) == 0.0; + } - [LispLibrary("feersum", "serehfa", "arithmetics")] - public static class Arithmetics + [LispExport("+")] + public static object Arithadd(object[] args) { - [LispExport("zero?")] - public static object ArithZero(object[] args) - { - return UnpackArgs(args) == 0.0; - } + return ArithOp(args, 0.0, (a, b) => a + b); + } - [LispExport("+")] - public static object Arithadd(object[] args) - { - return ArithOp(args, 0.0, (a, b) => a + b); - } + [LispExport("-")] + public static object Arithsub(object[] args) + { + return ArithOp(args, 0.0, (a, b) => a - b); + } - [LispExport("-")] - public static object Arithsub(object[] args) - { - return ArithOp(args, 0.0, (a, b) => a - b); - } + [LispExport("/")] + public static object Arithdiv(object[] args) + { + return ArithOp(args, 1.0, (a, b) => a / b); + } - [LispExport("/")] - public static object Arithdiv(object[] args) - { - return ArithOp(args, 1.0, (a, b) => a / b); - } + [LispExport("*")] + public static object Arithmul(object[] args) + { + return ArithOp(args, 1.0, (a, b) => a * b); + } - [LispExport("*")] - public static object Arithmul(object[] args) - { - return ArithOp(args, 1.0, (a, b) => a * b); - } + [LispExport("=")] + public static object Aritheq(object[] args) + { + return ComparisonOp(args, (a, b) => a == b); + } - [LispExport("=")] - public static object Aritheq(object[] args) - { - return ComparisonOp(args, (a, b) => a == b); - } + [LispExport(">")] + public static object Arithgt(object[] args) + { + return ComparisonOp(args, (a, b) => a > b); + } - [LispExport(">")] - public static object Arithgt(object[] args) - { - return ComparisonOp(args, (a, b) => a > b); - } + [LispExport("<")] + public static object Arithlt(object[] args) + { + return ComparisonOp(args, (a, b) => a < b); + } - [LispExport("<")] - public static object Arithlt(object[] args) - { - return ComparisonOp(args, (a, b) => a < b); - } + [LispExport(">=")] + public static object Arithgte(object[] args) + { + return ComparisonOp(args, (a, b) => a >= b); + } - [LispExport(">=")] - public static object Arithgte(object[] args) + [LispExport("<=")] + public static object Arithlte(object[] args) + { + return ComparisonOp(args, (a, b) => a <= b); + } + + /// + /// Arithmetic builtin. Combines all elements in the arguments array with + /// the given . If only 1 element is provided then + /// is used to compute some form of inverse. If no + /// arguments are provided then is returned. + /// + /// The arguments to be combined. + /// The default value to use as a seed. + /// The operator to combine elements with + /// An arithmetic combination of the arguments. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static object ArithOp( + object[] args, + double def, + Func op) + { + double ret; + int i; + + if (args.Length < 2) { - return ComparisonOp(args, (a, b) => a >= b); + ret = def; + i = 0; } - - [LispExport("<=")] - public static object Arithlte(object[] args) + else { - return ComparisonOp(args, (a, b) => a <= b); + ret = Unpack(args[0]); + i = 1; } - /// - /// Arithmetic builtin. Combines all elements in the arguments array with - /// the given . If only 1 element is provided then - /// is used to compute some form of inverse. If no - /// arguments are provided then is returned. - /// - /// The arguments to be combined. - /// The default value to use as a seed. - /// The operator to combine elements with - /// An arithmetic combination of the arguments. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static object ArithOp( - object[] args, - double def, - Func op) + while (i < args.Length) { - double ret; - int i; - - if (args.Length < 2) - { - ret = def; - i = 0; - } - else - { - ret = Unpack(args[0]); - i = 1; - } - - while (i < args.Length) - { - ret = op(ret, Unpack(args[i++])); - } - - return ret; + ret = op(ret, Unpack(args[i++])); } - /// - /// Comparator Builtin. Builds a method which uses the given - /// compare all arguments and returns a - /// boolean result. If 0 or 1 elements are given the method will always - /// return #t. - /// - /// The arguments to compare - /// The comparison opertor to use. - /// - /// True if the sequence progresses with the operator, false otherwise - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static object ComparisonOp( - object[] args, Func comparator) + return ret; + } + + /// + /// Comparator Builtin. Builds a method which uses the given + /// compare all arguments and returns a + /// boolean result. If 0 or 1 elements are given the method will always + /// return #t. + /// + /// The arguments to compare + /// The comparison opertor to use. + /// + /// True if the sequence progresses with the operator, false otherwise + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static object ComparisonOp( + object[] args, Func comparator) + { + if (args.Length < 2) { - if (args.Length < 2) - { - return true; - } + return true; + } - var last = Unpack(args[0]); + var last = Unpack(args[0]); - for (int i = 1; i < args.Length; i++) + for (int i = 1; i < args.Length; i++) + { + var cur = Unpack(args[i]); + if (!comparator(last, cur)) { - var cur = Unpack(args[i]); - if (!comparator(last, cur)) - { - return false; - } - last = cur; + return false; } - return true; + last = cur; } + return true; } } diff --git a/src/Serehfa/Attributes/LispExportAttribute.cs b/src/Serehfa/Attributes/LispExportAttribute.cs index dd34c6c1..d9dec46d 100644 --- a/src/Serehfa/Attributes/LispExportAttribute.cs +++ b/src/Serehfa/Attributes/LispExportAttribute.cs @@ -1,21 +1,20 @@ using System; -namespace Serehfa.Attributes +namespace Serehfa.Attributes; + +/// Attribute to mark an exported lisp element +[AttributeUsage(AttributeTargets.Method)] +public class LispExportAttribute : Attribute { - /// Attribute to mark an exported lisp element - [AttributeUsage(AttributeTargets.Method)] - public class LispExportAttribute : Attribute + /// + /// Initialise an instance of + /// with the given external . + /// + public LispExportAttribute(string name) { - /// - /// Initialise an instance of - /// with the given external . - /// - public LispExportAttribute(string name) - { - Name = name; - } - - /// Gets the exported name of this builtin. - public string Name { get; } + Name = name; } + + /// Gets the exported name of this builtin. + public string Name { get; } } diff --git a/src/Serehfa/Attributes/LispLibraryAttribute.cs b/src/Serehfa/Attributes/LispLibraryAttribute.cs index 7588b52a..d6090e0e 100644 --- a/src/Serehfa/Attributes/LispLibraryAttribute.cs +++ b/src/Serehfa/Attributes/LispLibraryAttribute.cs @@ -1,22 +1,21 @@ using System; using System.Collections.Generic; -namespace Serehfa.Attributes +namespace Serehfa.Attributes; + +/// Attribute to mark scheme libraries. +[AttributeUsage(AttributeTargets.Class)] +public sealed class LispLibraryAttribute : Attribute { - /// Attribute to mark scheme libraries. - [AttributeUsage(AttributeTargets.Class)] - public sealed class LispLibraryAttribute : Attribute + /// + /// Initialise an instance of + /// + /// The library name. + public LispLibraryAttribute(params string[] name) { - /// - /// Initialise an instance of - /// - /// The library name. - public LispLibraryAttribute(params string[] name) - { - Name = name; - } - - /// The library's name - public IReadOnlyCollection Name { get; } + Name = name; } + + /// The library's name + public IReadOnlyCollection Name { get; } } diff --git a/src/Serehfa/Attributes/LispReExportAttribute.cs b/src/Serehfa/Attributes/LispReExportAttribute.cs index 23df215c..56bf9bd4 100644 --- a/src/Serehfa/Attributes/LispReExportAttribute.cs +++ b/src/Serehfa/Attributes/LispReExportAttribute.cs @@ -1,31 +1,30 @@ using System; -namespace Serehfa.Attributes +namespace Serehfa.Attributes; + +/// Attribute to mark a re-export exported lisp element +[AttributeUsage(AttributeTargets.Class)] +public class LispReExportAttribute : Attribute { - /// Attribute to mark a re-export exported lisp element - [AttributeUsage(AttributeTargets.Class)] - public class LispReExportAttribute : Attribute + /// + /// Initialise an instance of + /// with the given external . + /// + public LispReExportAttribute(string externName, Type libraryType, string libraryItem, bool isMethod) { - /// - /// Initialise an instance of - /// with the given external . - /// - public LispReExportAttribute(string externName, Type libraryType, string libraryItem, bool isMethod) - { - ExportedName = externName; - LibraryType = libraryType; - LibraryItem = libraryItem; - IsMethod = isMethod; - } + ExportedName = externName; + LibraryType = libraryType; + LibraryItem = libraryItem; + IsMethod = isMethod; + } - /// Gets the exported name of this builtin. - public string ExportedName { get; } + /// Gets the exported name of this builtin. + public string ExportedName { get; } - /// Gets the library the item is exported from - public Type LibraryType { get; } + /// Gets the library the item is exported from + public Type LibraryType { get; } - /// Gets the name of the item to re-export - public string LibraryItem { get; } - public bool IsMethod { get; } - } + /// Gets the name of the item to re-export + public string LibraryItem { get; } + public bool IsMethod { get; } } diff --git a/src/Serehfa/Booleans.cs b/src/Serehfa/Booleans.cs index c53435bf..e38650b2 100644 --- a/src/Serehfa/Booleans.cs +++ b/src/Serehfa/Booleans.cs @@ -1,40 +1,39 @@ using Serehfa.Attributes; -namespace Serehfa +namespace Serehfa; + +using static ArgHelpers; + +[LispLibrary("feersum", "serehfa", "booleans")] +public static class Booleans { - using static ArgHelpers; + [LispExport("not")] + public static object Not(object[] args) + { + return UnpackArgs(args) is false; + } - [LispLibrary("feersum", "serehfa", "booleans")] - public static class Booleans + [LispExport("boolean?")] + public static object IsBoolean(object[] args) { - [LispExport("not")] - public static object Not(object[] args) - { - return UnpackArgs(args) is false; - } + return UnpackArgs(args) is bool; + } - [LispExport("boolean?")] - public static object IsBoolean(object[] args) + [LispExport("boolean=?")] + public static object BooleanEq(object[] args) + { + CheckAtLeastArgs(args, 2); + if (args[0] is not bool comparand) { - return UnpackArgs(args) is bool; + return false; } - - [LispExport("boolean=?")] - public static object BooleanEq(object[] args) + for (int i = 0; i < args.Length; i++) { - CheckAtLeastArgs(args, 2); - if (args[0] is not bool comparand) + if (!(args[i] is bool b && b == comparand)) { return false; } - for (int i = 0; i < args.Length; i++) - { - if (!(args[i] is bool b && b == comparand)) - { - return false; - } - } - return true; } + return true; } } diff --git a/src/Serehfa/ByteVectors.cs b/src/Serehfa/ByteVectors.cs index a63034f9..f26d2462 100644 --- a/src/Serehfa/ByteVectors.cs +++ b/src/Serehfa/ByteVectors.cs @@ -1,98 +1,98 @@ using System; using System.Text; + using Serehfa.Attributes; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; + +using static ArgHelpers; - [LispLibrary("feersum", "serehfa", "bytevectors")] - public static class ByteVectors +[LispLibrary("feersum", "serehfa", "bytevectors")] +public static class ByteVectors +{ + [LispExport("bytevector?")] + public static object IsBytevector(object[] args) { - [LispExport("bytevector?")] - public static object IsBytevector(object[] args) - { - var maybeVec = UnpackArgs(args); + var maybeVec = UnpackArgs(args); - return maybeVec is byte[]; - } + return maybeVec is byte[]; + } - [LispExport("make-bytevector")] - public static object MakeBytevector(object[] args) - { - // TODO: Narrow down the types here when we support numerics better. - var (size, fill) = - args.Length == 1 ? - (UnpackArgs(args), default) : - UnpackArgs(args); - var byteFill = (byte)fill; + [LispExport("make-bytevector")] + public static object MakeBytevector(object[] args) + { + // TODO: Narrow down the types here when we support numerics better. + var (size, fill) = + args.Length == 1 ? + (UnpackArgs(args), default) : + UnpackArgs(args); + var byteFill = (byte)fill; - var vec = new byte[(int)size]; + var vec = new byte[(int)size]; - if (byteFill != default) + if (byteFill != default) + { + for (var i = 0; i < (int)size; i++) { - for (var i = 0; i < (int)size; i++) - { - vec[i] = byteFill; - } + vec[i] = byteFill; } - - return vec; } - [LispExport("bytevector-length")] - public static object BytevectorLength(object[] args) - { - var vec = UnpackArgs(args); - return (Double)vec.Length; - } + return vec; + } - [LispExport("bytevector-u8-set!")] - public static object BytevectorSet(object[] args) - { - var (vec, index, value) = UnpackArgs(args); - vec[(int)index] = (byte)value; - return null; - } + [LispExport("bytevector-length")] + public static object BytevectorLength(object[] args) + { + var vec = UnpackArgs(args); + return (Double)vec.Length; + } - [LispExport("bytevector-u8-ref")] - public static object BytevectorRef(object[] args) - { - var (vec, index) = UnpackArgs(args); - return (double)vec[(int)index]; - } + [LispExport("bytevector-u8-set!")] + public static object BytevectorSet(object[] args) + { + var (vec, index, value) = UnpackArgs(args); + vec[(int)index] = (byte)value; + return null; + } - [LispExport("bytevector")] - public static object NewBytevector(object[] args) - { - var vec = new byte[args.Length]; + [LispExport("bytevector-u8-ref")] + public static object BytevectorRef(object[] args) + { + var (vec, index) = UnpackArgs(args); + return (double)vec[(int)index]; + } - for (var i = 0; i < args.Length; i++) - { - var fill = (byte)Unpack(args[i]); - vec[i] = fill; - } + [LispExport("bytevector")] + public static object NewBytevector(object[] args) + { + var vec = new byte[args.Length]; - return vec; + for (var i = 0; i < args.Length; i++) + { + var fill = (byte)Unpack(args[i]); + vec[i] = fill; } - internal static string GetExternalRepresentation(byte[] bytes) + return vec; + } + + internal static string GetExternalRepresentation(byte[] bytes) + { + var sb = new StringBuilder(); + sb.Append("#u8("); + bool first = true; + foreach (var b in bytes) { - var sb = new StringBuilder(); - sb.Append("#u8("); - bool first = true; - foreach (var b in bytes) + if (!first) { - if (!first) - { - sb.Append(" "); - } - sb.Append(b); - first = false; + sb.Append(" "); } - - sb.Append(")"); - return sb.ToString(); + sb.Append(b); + first = false; } + + sb.Append(")"); + return sb.ToString(); } } diff --git a/src/Serehfa/Characters.cs b/src/Serehfa/Characters.cs index 579885dd..4312679c 100644 --- a/src/Serehfa/Characters.cs +++ b/src/Serehfa/Characters.cs @@ -1,192 +1,192 @@ using System; + using Serehfa.Attributes; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; + +using static ArgHelpers; - [LispLibrary("feersum", "serehfa", "characters")] - public static class Characters +[LispLibrary("feersum", "serehfa", "characters")] +public static class Characters +{ + [LispExport("char?")] + public static object IsChar(object[] args) { - [LispExport("char?")] - public static object IsChar(object[] args) - { - return UnpackArgs(args) is char; - } + return UnpackArgs(args) is char; + } - [LispExport("char=?")] - public static object CharEqual(object[] args) - { - return ComparisonOp(args, false, (c, d) => c == d); - } + [LispExport("char=?")] + public static object CharEqual(object[] args) + { + return ComparisonOp(args, false, (c, d) => c == d); + } - [LispExport("char c < d); - } + [LispExport("char c < d); + } - [LispExport("char>?")] - public static object CharGt(object[] args) - { - return ComparisonOp(args, false, (c, d) => c > d); - } + [LispExport("char>?")] + public static object CharGt(object[] args) + { + return ComparisonOp(args, false, (c, d) => c > d); + } - [LispExport("char<=?")] - public static object CharLte(object[] args) - { - return ComparisonOp(args, false, (c, d) => c <= d); - } + [LispExport("char<=?")] + public static object CharLte(object[] args) + { + return ComparisonOp(args, false, (c, d) => c <= d); + } - [LispExport("char>=?")] - public static object CharGte(object[] args) - { - return ComparisonOp(args, false, (c, d) => c >= d); - } + [LispExport("char>=?")] + public static object CharGte(object[] args) + { + return ComparisonOp(args, false, (c, d) => c >= d); + } - [LispExport("char-ci=?")] - public static object CharEqualCI(object[] args) - { - return ComparisonOp(args, true, (c, d) => c == d); - } + [LispExport("char-ci=?")] + public static object CharEqualCI(object[] args) + { + return ComparisonOp(args, true, (c, d) => c == d); + } - [LispExport("char-ci c < d); - } + [LispExport("char-ci c < d); + } - [LispExport("char-ci>?")] - public static object CharGtCi(object[] args) - { - return ComparisonOp(args, true, (c, d) => c > d); - } + [LispExport("char-ci>?")] + public static object CharGtCi(object[] args) + { + return ComparisonOp(args, true, (c, d) => c > d); + } - [LispExport("char-ci<=?")] - public static object CharLteCi(object[] args) - { - return ComparisonOp(args, true, (c, d) => c <= d); - } + [LispExport("char-ci<=?")] + public static object CharLteCi(object[] args) + { + return ComparisonOp(args, true, (c, d) => c <= d); + } - [LispExport("char-ci>=?")] - public static object CharGteCi(object[] args) - { - return ComparisonOp(args, true, (c, d) => c >= d); - } + [LispExport("char-ci>=?")] + public static object CharGteCi(object[] args) + { + return ComparisonOp(args, true, (c, d) => c >= d); + } - private static bool ComparisonOp( - object[] args, - bool foldCase, - Func comparator) + private static bool ComparisonOp( + object[] args, + bool foldCase, + Func comparator) + { + CheckAtLeastArgs(args, 2); + var last = Unpack(args[0]); + for (int i = 1; i < args.Length; i++) { - CheckAtLeastArgs(args, 2); - var last = Unpack(args[0]); - for (int i = 1; i < args.Length; i++) + var current = Unpack(args[i]); + if (!comparator(last, current)) { - var current = Unpack(args[i]); - if (!comparator(last, current)) - { - return false; - } - last = current; + return false; } - return true; + last = current; + } + return true; - uint Unpack(object input) + uint Unpack(object input) + { + var c = Unpack(input); + if (foldCase) { - var c = Unpack(input); - if (foldCase) - { - c = char.ToLowerInvariant(c); - } - return Convert.ToUInt32(c); + c = char.ToLowerInvariant(c); } + return Convert.ToUInt32(c); } + } - [LispExport("char-alphabetic?")] - public static object IsAlphabetic(object[] args) - { - return char.IsLetter(UnpackArgs(args)); - } + [LispExport("char-alphabetic?")] + public static object IsAlphabetic(object[] args) + { + return char.IsLetter(UnpackArgs(args)); + } - [LispExport("char-numeric?")] - public static object IsNumeric(object[] args) - { - return char.IsDigit(UnpackArgs(args)); - } + [LispExport("char-numeric?")] + public static object IsNumeric(object[] args) + { + return char.IsDigit(UnpackArgs(args)); + } - [LispExport("char-whitespace?")] - public static object IsWhitespace(object[] args) - { - return char.IsWhiteSpace(UnpackArgs(args)); - } + [LispExport("char-whitespace?")] + public static object IsWhitespace(object[] args) + { + return char.IsWhiteSpace(UnpackArgs(args)); + } - [LispExport("char-upper-case?")] - public static object IsUpper(object[] args) - { - return char.IsUpper(UnpackArgs(args)); - } + [LispExport("char-upper-case?")] + public static object IsUpper(object[] args) + { + return char.IsUpper(UnpackArgs(args)); + } - [LispExport("char-lower-case?")] - public static object IsLower(object[] args) - { - return char.IsLower(UnpackArgs(args)); - } + [LispExport("char-lower-case?")] + public static object IsLower(object[] args) + { + return char.IsLower(UnpackArgs(args)); + } - [LispExport("digit-value")] - public static object DigitValue(object[] args) + [LispExport("digit-value")] + public static object DigitValue(object[] args) + { + var c = UnpackArgs(args); + if (!char.IsDigit(c)) { - var c = UnpackArgs(args); - if (!char.IsDigit(c)) - { - return false; - } - return char.GetNumericValue(c); + return false; } + return char.GetNumericValue(c); + } - [LispExport("char->integer")] - public static object CharToNumber(object[] args) - { - return (double)(Convert.ToUInt32(UnpackArgs(args))); - } + [LispExport("char->integer")] + public static object CharToNumber(object[] args) + { + return (double)(Convert.ToUInt32(UnpackArgs(args))); + } - [LispExport("integer->char")] - public static object NumberToChar(object[] args) + [LispExport("integer->char")] + public static object NumberToChar(object[] args) + { + try { - try - { - if (char.TryParse( - char.ConvertFromUtf32( - (int)UnpackArgs(args)), out var res)) - { - return res; - } - } - catch (ArgumentOutOfRangeException) + if (char.TryParse( + char.ConvertFromUtf32( + (int)UnpackArgs(args)), out var res)) { - // If the character can't be parsed ignore that and fall through - // to the error return. + return res; } - return (double)(0x10FFFF + 1); } - - [LispExport("char-upcase")] - public static object CharUpcase(object[] args) + catch (ArgumentOutOfRangeException) { - return char.ToUpperInvariant(UnpackArgs(args)); + // If the character can't be parsed ignore that and fall through + // to the error return. } + return (double)(0x10FFFF + 1); + } - [LispExport("char-downcase")] - public static object CharDowncase(object[] args) - { - return char.ToLowerInvariant(UnpackArgs(args)); - } + [LispExport("char-upcase")] + public static object CharUpcase(object[] args) + { + return char.ToUpperInvariant(UnpackArgs(args)); + } - [LispExport("char-foldcase")] - public static object CharFoldcase(object[] args) - { - // Is this OK? - return CharDowncase(args); - } + [LispExport("char-downcase")] + public static object CharDowncase(object[] args) + { + return char.ToLowerInvariant(UnpackArgs(args)); + } + + [LispExport("char-foldcase")] + public static object CharFoldcase(object[] args) + { + // Is this OK? + return CharDowncase(args); } } diff --git a/src/Serehfa/ConsPair.cs b/src/Serehfa/ConsPair.cs index 536831a7..fdbc56e0 100644 --- a/src/Serehfa/ConsPair.cs +++ b/src/Serehfa/ConsPair.cs @@ -1,44 +1,43 @@ using System.Text; -namespace Serehfa +namespace Serehfa; + +public class ConsPair { - public class ConsPair + public ConsPair(object car, object cdr) { - public ConsPair(object car, object cdr) - { - Car = car; - Cdr = cdr; - } + Car = car; + Cdr = cdr; + } - public object Car { get; set; } - public object Cdr { get; set; } + public object Car { get; set; } + public object Cdr { get; set; } - public override string ToString() + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("("); + var current = this; + while (current != null) { - var sb = new StringBuilder(); - sb.Append("("); - var current = this; - while (current != null) + sb.Append(Write.GetExternalRepresentation(current.Car)); + if (current.Cdr is ConsPair tail) + { + sb.Append(" "); + current = tail; + } + else if (current.Cdr is null) + { + current = null; + } + else { - sb.Append(Write.GetExternalRepresentation(current.Car)); - if (current.Cdr is ConsPair tail) - { - sb.Append(" "); - current = tail; - } - else if (current.Cdr is null) - { - current = null; - } - else - { - sb.Append(" . "); - sb.Append(Write.GetExternalRepresentation(current.Cdr)); - break; - } + sb.Append(" . "); + sb.Append(Write.GetExternalRepresentation(current.Cdr)); + break; } - sb.Append(")"); - return sb.ToString(); } + sb.Append(")"); + return sb.ToString(); } } diff --git a/src/Serehfa/Core.cs b/src/Serehfa/Core.cs index 1678ad1c..28d9bdfe 100644 --- a/src/Serehfa/Core.cs +++ b/src/Serehfa/Core.cs @@ -1,26 +1,26 @@ using System; using System.Linq; + using Serehfa.Attributes; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; + +using static ArgHelpers; - [LispLibrary("feersum", "serehfa", "core")] - public static class Core +[LispLibrary("feersum", "serehfa", "core")] +public static class Core +{ + [LispExport("procedure?")] + public static object IsProcedure(object[] args) { - [LispExport("procedure?")] - public static object IsProcedure(object[] args) - { - var proc = UnpackArgs(args); - return proc is Func; - } + var proc = UnpackArgs(args); + return proc is Func; + } - [LispExport("core-apply-vec")] - public static object CoreApply(object[] args) - { - var (target, targetArgs) = UnpackArgs, object[]>(args); - return target(targetArgs); - } + [LispExport("core-apply-vec")] + public static object CoreApply(object[] args) + { + var (target, targetArgs) = UnpackArgs, object[]>(args); + return target(targetArgs); } } diff --git a/src/Serehfa/Equivalence.cs b/src/Serehfa/Equivalence.cs index 56b23642..e691f909 100644 --- a/src/Serehfa/Equivalence.cs +++ b/src/Serehfa/Equivalence.cs @@ -1,124 +1,124 @@ using System; using System.Collections.Generic; + using Serehfa.Attributes; -namespace Serehfa +namespace Serehfa; + +using static ArgHelpers; + +[LispLibrary("feersum", "serehfa", "equivalence")] +public static class Equivalence { - using static ArgHelpers; + /// + /// Object equivalence check. This is a slightly more fuzzy + /// version of eq?, but with value equivalence for + /// Our various boxed values. + /// + [LispExport("eqv?")] + public static object Equiv(object[] args) + { + return UnpackArgs(args) switch + { + (bool a, bool b) => a == b, + (Ident a, Ident b) => a.Equals(b), + (double a, double b) => a == b, + (char a, char b) => a == b, + (Func a, Func b) => + a.Target == b.Target && a.Method == b.Method, + (null, null) => true, + (object lhs, object rhs) => + (lhs != null && rhs != null) && + object.ReferenceEquals(lhs, rhs), + }; + } - [LispLibrary("feersum", "serehfa", "equivalence")] - public static class Equivalence + /// + /// Simple pointer-style equivalence. For our scheme we have + /// to handle identifiers + procedures specially as they + /// aren't completely transparent references. + /// + [LispExport("eq?")] + public static object Eq(object[] args) { - /// - /// Object equivalence check. This is a slightly more fuzzy - /// version of eq?, but with value equivalence for - /// Our various boxed values. - /// - [LispExport("eqv?")] - public static object Equiv(object[] args) + return UnpackArgs(args) switch { - return UnpackArgs(args) switch - { - (bool a, bool b) => a == b, - (Ident a, Ident b) => a.Equals(b), - (double a, double b) => a == b, - (char a, char b) => a == b, - (Func a, Func b) => - a.Target == b.Target && a.Method == b.Method, - (null, null) => true, - (object lhs, object rhs) => - (lhs != null && rhs != null) && - object.ReferenceEquals(lhs, rhs), - }; - } + (Ident a, Ident b) => a.Equals(b), + (Func a, Func b) => + a.Target == b.Target && a.Method == b.Method, + (null, null) => true, + (object lhs, object rhs) => + (lhs != null && rhs != null) && + object.ReferenceEquals(lhs, rhs), + }; + } + + [LispExport("equal?")] + public static object Equal(object[] args) + { + var (left, right) = UnpackArgs(args); + return LispEqualityComparer.Default.Equals(left, right); + } - /// - /// Simple pointer-style equivalence. For our scheme we have - /// to handle identifiers + procedures specially as they - /// aren't completely transparent references. - /// - [LispExport("eq?")] - public static object Eq(object[] args) + private class LispEqualityComparer : EqualityComparer + { + public override bool Equals(object left, object right) { - return UnpackArgs(args) switch + return (left, right) switch { - (Ident a, Ident b) => a.Equals(b), - (Func a, Func b) => - a.Target == b.Target && a.Method == b.Method, - (null, null) => true, - (object lhs, object rhs) => - (lhs != null && rhs != null) && - object.ReferenceEquals(lhs, rhs), + (ConsPair l, ConsPair r) => + Equals(l.Car, r.Car) && Equals(l.Cdr, r.Cdr), + (object[] l, object[] r) => ArrayEq(l, r), + (bool[] l, bool[] r) => ArrayEq(l, r), + _ => EqualityComparer.Default.Equals(left, right), }; } - [LispExport("equal?")] - public static object Equal(object[] args) - { - var (left, right) = UnpackArgs(args); - return LispEqualityComparer.Default.Equals(left, right); - } - - private class LispEqualityComparer : EqualityComparer + private bool ArrayEq(T[] left, T[] right) { - public override bool Equals(object left, object right) + if (left.Length != right.Length) { - return (left, right) switch - { - (ConsPair l, ConsPair r) => - Equals(l.Car, r.Car) && Equals(l.Cdr, r.Cdr), - (object[] l, object[] r) => ArrayEq(l, r), - (bool[] l, bool[] r) => ArrayEq(l, r), - _ => EqualityComparer.Default.Equals(left, right), - }; + return false; } - private bool ArrayEq(T[] left, T[] right) + for (int i = 0; i < left.Length; i++) { - if (left.Length != right.Length) + if (!Equals(left[i], right[i])) { return false; } - - for (int i = 0; i < left.Length; i++) - { - if (!Equals(left[i], right[i])) - { - return false; - } - } - - return true; } - public override int GetHashCode(object o) + return true; + } + + public override int GetHashCode(object o) + { + return o switch { - return o switch - { - ConsPair p => - (p.Car, p.Cdr).GetHashCode(), - object[] v => ArrayHash(v), - bool[] bv => ArrayHash(bv), - _ => EqualityComparer.Default.GetHashCode(o), - }; - } + ConsPair p => + (p.Car, p.Cdr).GetHashCode(), + object[] v => ArrayHash(v), + bool[] bv => ArrayHash(bv), + _ => EqualityComparer.Default.GetHashCode(o), + }; + } - private int ArrayHash(T[] v) + private int ArrayHash(T[] v) + { + unchecked { - unchecked + var hash = 0xcbf29ce484222325; + foreach (var item in v) { - var hash = 0xcbf29ce484222325; - foreach (var item in v) - { - hash ^= (ulong)item.GetHashCode(); - hash *= 0x100000001b3; - } - return (int)hash; + hash ^= (ulong)item.GetHashCode(); + hash *= 0x100000001b3; } + return (int)hash; } - - public new static LispEqualityComparer Default { get; } = - new LispEqualityComparer(); } + + public new static LispEqualityComparer Default { get; } = + new LispEqualityComparer(); } } diff --git a/src/Serehfa/Ident.cs b/src/Serehfa/Ident.cs index 2148e468..1b9ff6a8 100644 --- a/src/Serehfa/Ident.cs +++ b/src/Serehfa/Ident.cs @@ -2,69 +2,68 @@ using System.Linq; using System.Text; -namespace Serehfa +namespace Serehfa; + +public class Ident { - public class Ident - { - private readonly string _id; + private readonly string _id; - public Ident(string id) - { - _id = string.Intern(id); - } + public Ident(string id) + { + _id = string.Intern(id); + } - public bool IsSimple => _id.All(c => char.IsLetterOrDigit(c)); + public bool IsSimple => _id.All(c => char.IsLetterOrDigit(c)); - public string Raw => _id; + public string Raw => _id; - public override int GetHashCode() => (_id).GetHashCode(); + public override int GetHashCode() => (_id).GetHashCode(); - public override bool Equals(object obj) => obj switch - { - Ident other => _id == other._id, - _ => false, - }; + public override bool Equals(object obj) => obj switch + { + Ident other => _id == other._id, + _ => false, + }; - public override string ToString() => IsSimple ? - _id : Quote(_id); + public override string ToString() => IsSimple ? + _id : Quote(_id); - private static string Quote(string id) + private static string Quote(string id) + { + var sb = new StringBuilder(); + sb.Append("|"); + foreach (var c in id) { - var sb = new StringBuilder(); - sb.Append("|"); - foreach (var c in id) + switch (c) { - switch (c) - { - case '\\': - case '|': - sb.AppendFormat("\\{0}", c); - break; - case ' ': sb.Append(' '); break; - default: - if (char.IsWhiteSpace(c)) - { - sb.AppendFormat("\\x{0:X};", (int)c); - } - else - { - sb.Append(c); - } - break; - } + case '\\': + case '|': + sb.AppendFormat("\\{0}", c); + break; + case ' ': sb.Append(' '); break; + default: + if (char.IsWhiteSpace(c)) + { + sb.AppendFormat("\\x{0:X};", (int)c); + } + else + { + sb.Append(c); + } + break; } - sb.Append("|"); - return sb.ToString(); } + sb.Append("|"); + return sb.ToString(); + } - public static bool operator ==(Ident lhs, Ident rhs) - { - return lhs._id == rhs._id; - } + public static bool operator ==(Ident lhs, Ident rhs) + { + return lhs._id == rhs._id; + } - public static bool operator !=(Ident lhs, Ident rhs) - { - return lhs._id != rhs._id; - } + public static bool operator !=(Ident lhs, Ident rhs) + { + return lhs._id != rhs._id; } } diff --git a/src/Serehfa/Lists.cs b/src/Serehfa/Lists.cs index 09042ff4..85283feb 100644 --- a/src/Serehfa/Lists.cs +++ b/src/Serehfa/Lists.cs @@ -1,128 +1,129 @@ using Serehfa.Attributes; -namespace Serehfa +namespace Serehfa; + +using static ArgHelpers; + + +[LispLibrary("feersum", "serehfa", "lists")] +public class Lists { - using static ArgHelpers; + [LispExport("null?")] + public static object NullCheck(object[] args) + { + return UnpackArgs(args) == null; + } + [LispExport("cons")] + public static object Cons(object[] args) + { + var (left, right) = UnpackArgs(args); + return new ConsPair(left, right); + } - [LispLibrary("feersum", "serehfa", "lists")] - public class Lists + [LispExport("list")] + public static object ListNew(object[] args) { - [LispExport("null?")] - public static object NullCheck(object[] args) + ConsPair ret = null; + for (int i = args.Length; i > 0; i--) { - return UnpackArgs(args) == null; + ret = new ConsPair(args[i - 1], ret); } - [LispExport("cons")] - public static object Cons(object[] args) - { - var (left, right) = UnpackArgs(args); - return new ConsPair(left, right); - } + return ret; + } - [LispExport("list")] - public static object ListNew(object[] args) + [LispExport("make-list")] + public static object MakeList(object[] args) + { + object fill = null; + double length; + if (args.Length == 1) { - ConsPair ret = null; - for (int i = args.Length; i > 0; i--) - { - ret = new ConsPair(args[i - 1], ret); - } - return ret; + length = UnpackArgs(args); } - - [LispExport("make-list")] - public static object MakeList(object[] args) + else { - object fill = null; - double length; - if (args.Length == 1) - { - length = UnpackArgs(args); - } - else - { - (length, fill) = UnpackArgs(args); - } - - ConsPair tail = null; - - for (int i = 0; i < length; i++) - { - tail = new ConsPair(fill, tail); - } - - return tail; + (length, fill) = UnpackArgs(args); } - [LispExport("pair?")] - public static object IsPair(object[] args) - { - var toTest = UnpackArgs(args); - return toTest is ConsPair; - } + ConsPair tail = null; - [LispExport("list?")] - public static object IsList(object[] args) + for (int i = 0; i < length; i++) { - var toTest = UnpackArgs(args); - return toTest switch - { - null => true, - ConsPair pair => (pair.Cdr == null || pair.Cdr is ConsPair), - _ => false, - }; + tail = new ConsPair(fill, tail); } - [LispExport("car")] - public static object Car(object[] args) - { - var list = UnpackArgs(args); - return list.Car; - } + return tail; + } - [LispExport("cdr")] - public static object Cdr(object[] args) - { - var list = UnpackArgs(args); - return list.Cdr; - } + [LispExport("pair?")] + public static object IsPair(object[] args) + { + var toTest = UnpackArgs(args); + return toTest is ConsPair; + } - [LispExport("set-car!")] - public static object SetCar(object[] args) + [LispExport("list?")] + public static object IsList(object[] args) + { + var toTest = UnpackArgs(args); + return toTest switch { - var (list, newCar) = UnpackArgs(args); - list.Car = newCar; - return Undefined.Instance; - } + null => true, + ConsPair pair => (pair.Cdr == null || pair.Cdr is ConsPair), + _ => false, + }; + } - [LispExport("set-cdr!")] - public static object SetCdr(object[] args) - { - var (list, newCdr) = UnpackArgs(args); - list.Cdr = newCdr; - return Undefined.Instance; - } + [LispExport("car")] + public static object Car(object[] args) + { + var list = UnpackArgs(args); + return list.Car; + } - [LispExport("length")] - public static object Length(object[] args) + [LispExport("cdr")] + public static object Cdr(object[] args) + { + var list = UnpackArgs(args); + return list.Cdr; + } + + [LispExport("set-car!")] + public static object SetCar(object[] args) + { + var (list, newCar) = UnpackArgs(args); + list.Car = newCar; + return Undefined.Instance; + } + + [LispExport("set-cdr!")] + public static object SetCdr(object[] args) + { + var (list, newCdr) = UnpackArgs(args); + list.Cdr = newCdr; + return Undefined.Instance; + } + + [LispExport("length")] + public static object Length(object[] args) + { + var list = UnpackArgs(args); + var length = 0; + while (list != null) { - var list = UnpackArgs(args); - var length = 0; - while (list != null) + length++; + if (list.Cdr is ConsPair tail) + { + list = tail; + } + else { - length++; - if (list.Cdr is ConsPair tail) - { - list = tail; - } - else - { - break; - } + break; } - return (double)length; } + + return (double)length; } } diff --git a/src/Serehfa/ProcessContext.cs b/src/Serehfa/ProcessContext.cs index a08ab91d..7bd6d03d 100644 --- a/src/Serehfa/ProcessContext.cs +++ b/src/Serehfa/ProcessContext.cs @@ -1,74 +1,76 @@ using System; using System.Linq; + using Serehfa.Attributes; + using static Serehfa.ArgHelpers; -namespace Serehfa +namespace Serehfa; + +[LispLibrary("scheme", "process-context")] +public static class ProcessContext { - [LispLibrary("scheme", "process-context")] - public static class ProcessContext + [LispExport("command-line")] + public static object GetCommandLine(object[] args) { - [LispExport("command-line")] - public static object GetCommandLine(object[] args) - { - CheckNoArgs(args); - return Lists.ListNew( - Environment.GetCommandLineArgs() - .Cast() - .ToArray()); - } + CheckNoArgs(args); + return Lists.ListNew( + Environment.GetCommandLineArgs() + .Cast() + .ToArray()); + } - [LispExport("exit")] - public static object Exit(object[] args) - { - Environment.Exit(ExitStatusFromArgs(args)); - return null; - } + [LispExport("exit")] + public static object Exit(object[] args) + { + Environment.Exit(ExitStatusFromArgs(args)); + return null; + } - [LispExport("emergency-exit")] - public static object EmergencyExit(object[] args) - { - Environment.ExitCode = ExitStatusFromArgs(args); - Environment.FailFast("Scheme emergency exit"); - return null; - } + [LispExport("emergency-exit")] + public static object EmergencyExit(object[] args) + { + Environment.ExitCode = ExitStatusFromArgs(args); + Environment.FailFast("Scheme emergency exit"); + return null; + } + + [LispExport("get-environment-variable")] + public static object GetEnvironmentVariable(object[] args) + { + var name = UnpackArgs(args); + return Environment.GetEnvironmentVariable(name); + } - [LispExport("get-environment-variable")] - public static object GetEnvironmentVariable(object[] args) + [LispExport("get-environment-variables")] + public static object GetEnvironmentVariables(object[] args) + { + CheckNoArgs(args); + var envVars = Environment.GetEnvironmentVariables(); + var envVarsAlist = new object[envVars.Count]; + int i = 0; + foreach (System.Collections.DictionaryEntry envVar in envVars) { - var name = UnpackArgs(args); - return Environment.GetEnvironmentVariable(name); + envVarsAlist[i++] = new ConsPair(envVar.Key.ToString(), envVar.Value.ToString()); } - [LispExport("get-environment-variables")] - public static object GetEnvironmentVariables(object[] args) + return Lists.ListNew(envVarsAlist); + } + + private static int ExitStatusFromArgs(object[] args) + { + if (args.Length == 0) { - CheckNoArgs(args); - var envVars = Environment.GetEnvironmentVariables(); - var envVarsAlist = new object[envVars.Count]; - int i = 0; - foreach (System.Collections.DictionaryEntry envVar in envVars) - { - envVarsAlist[i++] = new ConsPair(envVar.Key.ToString(), envVar.Value.ToString()); - } - return Lists.ListNew(envVarsAlist); + return 0; } - private static int ExitStatusFromArgs(object[] args) + return UnpackArgs(args) switch { - if (args.Length == 0) - { - return 0; - } - - return UnpackArgs(args) switch - { - true => 0, - false => 255, - double d => (int)d, - int i => i, - object other => other.GetHashCode(), - }; - } + true => 0, + false => 255, + double d => (int)d, + int i => i, + object other => other.GetHashCode(), + }; } } diff --git a/src/Serehfa/RandomBits.cs b/src/Serehfa/RandomBits.cs index c0f31839..53e577a8 100644 --- a/src/Serehfa/RandomBits.cs +++ b/src/Serehfa/RandomBits.cs @@ -1,33 +1,34 @@ using System; + using Serehfa.Attributes; + using static Serehfa.ArgHelpers; -namespace Serehfa +namespace Serehfa; + +[LispLibrary("feersum", "serehfa", "random-bits")] +public static class RandomBits { - [LispLibrary("feersum", "serehfa", "random-bits")] - public static class RandomBits + [LispExport("random-integer")] + public static object RandomInt(object[] args) { - [LispExport("random-integer")] - public static object RandomInt(object[] args) + // FIXME: fixup for fixnums. + var max = UnpackArgs(args); + lock (s_RandomInstance) { - // FIXME: fixup for fixnums. - var max = UnpackArgs(args); - lock (s_RandomInstance) - { - return (double)s_RandomInstance.Next((int)max); - } + return (double)s_RandomInstance.Next((int)max); } + } - [LispExport("random-real")] - public static object RandomDouble(object[] args) + [LispExport("random-real")] + public static object RandomDouble(object[] args) + { + CheckNoArgs(args); + lock (s_RandomInstance) { - CheckNoArgs(args); - lock (s_RandomInstance) - { - return s_RandomInstance.NextDouble(); - } + return s_RandomInstance.NextDouble(); } - - private static readonly Random s_RandomInstance = new(); } + + private static readonly Random s_RandomInstance = new(); } diff --git a/src/Serehfa/Read.cs b/src/Serehfa/Read.cs index ea33fe10..c02fc5ce 100644 --- a/src/Serehfa/Read.cs +++ b/src/Serehfa/Read.cs @@ -1,105 +1,105 @@ using System; +using System.Runtime.InteropServices; using System.Text; + using Serehfa.Attributes; -using System.Runtime.InteropServices; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; - [LispLibrary("feersum", "serehfa", "read")] - public static class Read - { - [LispExport("read-char")] - public static object ReadChar(object[] args) - { - CheckNoArgs(args); +using static ArgHelpers; - var read = Console.In.Read(); - if (read < 0) - { - return Eof.Instance; - } - - return (char)read; - } +[LispLibrary("feersum", "serehfa", "read")] +public static class Read +{ + [LispExport("read-char")] + public static object ReadChar(object[] args) + { + CheckNoArgs(args); - [LispExport("peek-char")] - public static object PeekChar(object[] args) + var read = Console.In.Read(); + if (read < 0) { - CheckNoArgs(args); + return Eof.Instance; + } - var read = Console.In.Peek(); - if (read < 0) - { - return Eof.Instance; - } + return (char)read; + } - return (char)read; - } + [LispExport("peek-char")] + public static object PeekChar(object[] args) + { + CheckNoArgs(args); - [LispExport("read-line")] - public static object ReadLine(object[] args) + var read = Console.In.Peek(); + if (read < 0) { - CheckNoArgs(args); + return Eof.Instance; + } - var read = Console.In.ReadLine(); - if (read == null) - { - return Eof.Instance; - } + return (char)read; + } - return read; - } + [LispExport("read-line")] + public static object ReadLine(object[] args) + { + CheckNoArgs(args); - [LispExport("eof-object")] - public static object MakeEofObject(object[] args) + var read = Console.In.ReadLine(); + if (read == null) { - CheckNoArgs(args); return Eof.Instance; } - [LispExport("eof-object?")] - public static object IsEofObject(object[] args) - { - var toCheck = UnpackArgs(args); - return Eof.Instance == toCheck; - } + return read; + } - [LispExport("char-ready?")] - public static object CharReady(object[] args) - { - CheckNoArgs(args); + [LispExport("eof-object")] + public static object MakeEofObject(object[] args) + { + CheckNoArgs(args); + return Eof.Instance; + } - return Console.KeyAvailable; - } + [LispExport("eof-object?")] + public static object IsEofObject(object[] args) + { + var toCheck = UnpackArgs(args); + return Eof.Instance == toCheck; + } - [LispExport("read-string")] - public static object ReadString(object[] args) - { - var len = (int)UnpackArgs(args); - var buff = new char[len]; - var read = Console.In.Read(buff, 0, len); + [LispExport("char-ready?")] + public static object CharReady(object[] args) + { + CheckNoArgs(args); - if (read == 0) - { - return Eof.Instance; - } + return Console.KeyAvailable; + } - return new String(buff, 0, read); - } + [LispExport("read-string")] + public static object ReadString(object[] args) + { + var len = (int)UnpackArgs(args); + var buff = new char[len]; + var read = Console.In.Read(buff, 0, len); - /// Marker type to rerepresent the end of file - private class Eof + if (read == 0) { - private Eof() { } + return Eof.Instance; + } - /// - public override string ToString() => - "#"; + return new String(buff, 0, read); + } - /// Singleton instance of the EOF. - public static Eof Instance = new(); - } + /// Marker type to rerepresent the end of file + private class Eof + { + private Eof() { } + + /// + public override string ToString() => + "#"; + + /// Singleton instance of the EOF. + public static Eof Instance = new(); } } diff --git a/src/Serehfa/Strings.cs b/src/Serehfa/Strings.cs index e8e1e3b4..6a64cbd3 100644 --- a/src/Serehfa/Strings.cs +++ b/src/Serehfa/Strings.cs @@ -1,57 +1,59 @@ using System; using System.Text; + using Serehfa.Attributes; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; + +using static ArgHelpers; - [LispLibrary("feersum", "serehfa", "strings")] - public static class Strings +[LispLibrary("feersum", "serehfa", "strings")] +public static class Strings +{ + [LispExport("string=?")] + public static object StringEquals(object[] args) { - [LispExport("string=?")] - public static object StringEquals(object[] args) + CheckAtLeastArgs(args, 2); + if (args[0] is not string comparand) { - CheckAtLeastArgs(args, 2); - if (args[0] is not string comparand) - { - return false; - } - for (int i = 1; i < args.Length; i++) - { - if (!(args[i] is string s && s == comparand)) - { - return false; - } - } - return true; + return false; } - [LispExport("string->number")] - public static object StringToNumber(object[] args) + for (int i = 1; i < args.Length; i++) { - if (args.Length == 1) + if (!(args[i] is string s && s == comparand)) { - return double.Parse(UnpackArgs(args)); + return false; } - - var (input, bae) = UnpackArgs(args); - return (double)Convert.ToUInt64(input, (int)bae); } - [LispExport("string-append")] - public static object StringAppend(object[] args) + return true; + } + + [LispExport("string->number")] + public static object StringToNumber(object[] args) + { + if (args.Length == 1) { - CheckAtLeastArgs(args, 1); + return double.Parse(UnpackArgs(args)); + } - var sb = new StringBuilder(Unpack(args[0])); - for (int i = 1; i < args.Length; i++) - { - var toAppend = Unpack(args[i]); - sb.Append(toAppend); - } + var (input, bae) = UnpackArgs(args); + return (double)Convert.ToUInt64(input, (int)bae); + } + + [LispExport("string-append")] + public static object StringAppend(object[] args) + { + CheckAtLeastArgs(args, 1); - return sb.ToString(); + var sb = new StringBuilder(Unpack(args[0])); + for (int i = 1; i < args.Length; i++) + { + var toAppend = Unpack(args[i]); + sb.Append(toAppend); } + + return sb.ToString(); } } diff --git a/src/Serehfa/Symbols.cs b/src/Serehfa/Symbols.cs index 62494744..ddaffc42 100644 --- a/src/Serehfa/Symbols.cs +++ b/src/Serehfa/Symbols.cs @@ -1,46 +1,47 @@ using Serehfa.Attributes; -namespace Serehfa +namespace Serehfa; + +using static ArgHelpers; + +[LispLibrary("feersum", "serehfa", "symbols")] +public static class Symbols { - using static ArgHelpers; + [LispExport("symbol?")] + public static object IsSymbol(object[] args) + { + return UnpackArgs(args) is Ident; + } - [LispLibrary("feersum", "serehfa", "symbols")] - public static class Symbols + [LispExport("symbol=?")] + public static object SymbolEquals(object[] args) { - [LispExport("symbol?")] - public static object IsSymbol(object[] args) + CheckAtLeastArgs(args, 2); + if (args[0] is not Ident comparand) { - return UnpackArgs(args) is Ident; + return false; } - [LispExport("symbol=?")] - public static object SymbolEquals(object[] args) + for (int i = 1; i < args.Length; i++) { - CheckAtLeastArgs(args, 2); - if (args[0] is not Ident comparand) + if (!(args[i] is Ident id && id == comparand)) { return false; } - for (int i = 1; i < args.Length; i++) - { - if (!(args[i] is Ident id && id == comparand)) - { - return false; - } - } - return true; } - [LispExport("symbol->string")] - public static object SymbolToString(object[] args) - { - return UnpackArgs(args).Raw; - } + return true; + } - [LispExport("string->symbol")] - public static object StringToSymbol(object[] args) - { - return new Ident(UnpackArgs(args)); - } + [LispExport("symbol->string")] + public static object SymbolToString(object[] args) + { + return UnpackArgs(args).Raw; + } + + [LispExport("string->symbol")] + public static object StringToSymbol(object[] args) + { + return new Ident(UnpackArgs(args)); } } diff --git a/src/Serehfa/Time.cs b/src/Serehfa/Time.cs index b69f69f3..dd1c9d6d 100644 --- a/src/Serehfa/Time.cs +++ b/src/Serehfa/Time.cs @@ -1,36 +1,36 @@ using System; -using Serehfa.Attributes; using System.Diagnostics; -namespace Serehfa -{ - using static ArgHelpers; +using Serehfa.Attributes; + +namespace Serehfa; + +using static ArgHelpers; - [LispLibrary("scheme", "time")] - public static class Time +[LispLibrary("scheme", "time")] +public static class Time +{ + [LispExport("current-second")] + public static object CurrentSecond(object[] args) { - [LispExport("current-second")] - public static object CurrentSecond(object[] args) - { - CheckNoArgs(args); - // FIXME: return fixnum - return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0; - } + CheckNoArgs(args); + // FIXME: return fixnum + return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0; + } - [LispExport("current-jiffy")] - public static object CurrentJiffy(object[] args) - { - CheckNoArgs(args); - // FIXME: return fixnum - return (double)Stopwatch.GetTimestamp(); - } + [LispExport("current-jiffy")] + public static object CurrentJiffy(object[] args) + { + CheckNoArgs(args); + // FIXME: return fixnum + return (double)Stopwatch.GetTimestamp(); + } - [LispExport("jiffies-per-second")] - public static object JiffiesPerSeconds(object[] args) - { - CheckNoArgs(args); - // FIXME: return fixnum - return (double)Stopwatch.Frequency; - } + [LispExport("jiffies-per-second")] + public static object JiffiesPerSeconds(object[] args) + { + CheckNoArgs(args); + // FIXME: return fixnum + return (double)Stopwatch.Frequency; } } diff --git a/src/Serehfa/Undefined.cs b/src/Serehfa/Undefined.cs index 86457fb2..687fd7c3 100644 --- a/src/Serehfa/Undefined.cs +++ b/src/Serehfa/Undefined.cs @@ -1,30 +1,29 @@ using System; -namespace Serehfa +namespace Serehfa; + +/// +/// The unspecified / undefined value. Instances of this type are returned +/// from scheme functions where no specific return value is specified in +/// the standard. +/// +public class Undefined { - /// - /// The unspecified / undefined value. Instances of this type are returned - /// from scheme functions where no specific return value is specified in - /// the standard. - /// - public class Undefined - { - private static readonly Lazy s_Instance = new(); + private static readonly Lazy s_Instance = new(); - /// Shared instance of the undefined type. References to this - /// are emitted by the compiler when an undefined value is required. - /// - public static Undefined Instance => s_Instance.Value; + /// Shared instance of the undefined type. References to this + /// are emitted by the compiler when an undefined value is required. + /// + public static Undefined Instance => s_Instance.Value; - /// - public override string ToString() => "; Unspecified value"; + /// + public override string ToString() => "; Unspecified value"; - /// - /// Instances of these values are never equal to anything else. - /// - public override bool Equals(object obj) => false; + /// + /// Instances of these values are never equal to anything else. + /// + public override bool Equals(object obj) => false; - /// - public override int GetHashCode() => base.GetHashCode(); - } + /// + public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/Serehfa/Vectors.cs b/src/Serehfa/Vectors.cs index c14bb8a2..98ea0067 100644 --- a/src/Serehfa/Vectors.cs +++ b/src/Serehfa/Vectors.cs @@ -1,90 +1,92 @@ using System; using System.Collections.Generic; using System.Text; + using Serehfa.Attributes; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; - /// - /// Methods to interact with Scheme vectors. Our scheme vector - /// implementation uses the .NET . - /// - [LispLibrary("feersum", "serehfa", "vectors")] - public static class Vectors +using static ArgHelpers; + +/// +/// Methods to interact with Scheme vectors. Our scheme vector +/// implementation uses the .NET . +/// +[LispLibrary("feersum", "serehfa", "vectors")] +public static class Vectors +{ + [LispExport("vector")] + public static object VectorNew(object[] args) { - [LispExport("vector")] - public static object VectorNew(object[] args) - { - return args; - } + return args; + } - [LispExport("vector?")] - public static object IsVector(object[] args) - { - var vec = UnpackArgs(args); - return vec is object[]; - } + [LispExport("vector?")] + public static object IsVector(object[] args) + { + var vec = UnpackArgs(args); + return vec is object[]; + } - [LispExport("vector-length")] - public static object VectorLength(object[] args) - { - var vec = UnpackArgs(args); - return (Double)vec.Length; - } + [LispExport("vector-length")] + public static object VectorLength(object[] args) + { + var vec = UnpackArgs(args); + return (Double)vec.Length; + } - [LispExport("vector-set!")] - public static object VectorSet(object[] args) - { - var (vec, index, value) = UnpackArgs(args); - vec[(int)index] = value; - return null; - } + [LispExport("vector-set!")] + public static object VectorSet(object[] args) + { + var (vec, index, value) = UnpackArgs(args); + vec[(int)index] = value; + return null; + } - [LispExport("vector-ref")] - public static object VectorRef(object[] args) - { - var (vec, index) = UnpackArgs(args); - return vec[(int)index]; - } + [LispExport("vector-ref")] + public static object VectorRef(object[] args) + { + var (vec, index) = UnpackArgs(args); + return vec[(int)index]; + } - [LispExport("make-vector")] - public static object MakeVector(object[] args) + [LispExport("make-vector")] + public static object MakeVector(object[] args) + { + var (size, init) = + args.Length == 1 ? + (UnpackArgs(args), default) : + UnpackArgs(args); + var isize = (int)size; + var vec = new object[isize]; + if (init != default) { - var (size, init) = - args.Length == 1 ? - (UnpackArgs(args), default) : - UnpackArgs(args); - var isize = (int)size; - var vec = new object[isize]; - if (init != default) + for (int i = 0; i < isize; i++) { - for (int i = 0; i < isize; i++) - { - vec[i] = init; - } + vec[i] = init; } - return vec; } - internal static string GetExternalRepresentation(object[] v) + return vec; + } + + internal static string GetExternalRepresentation(object[] v) + { + var sb = new StringBuilder(); + sb.Append("#("); + bool first = true; + foreach (var o in v) { - var sb = new StringBuilder(); - sb.Append("#("); - bool first = true; - foreach (var o in v) + if (!first) { - if (!first) - { - sb.Append(" "); - } - sb.Append(Write.GetExternalRepresentation(o)); - first = false; + sb.Append(" "); } - sb.Append(")"); - return sb.ToString(); + sb.Append(Write.GetExternalRepresentation(o)); + first = false; } + + sb.Append(")"); + return sb.ToString(); } } diff --git a/src/Serehfa/Write.cs b/src/Serehfa/Write.cs index fcb7253f..52728a58 100644 --- a/src/Serehfa/Write.cs +++ b/src/Serehfa/Write.cs @@ -1,115 +1,116 @@ using System; +using System.Runtime.InteropServices; using System.Text; + using Serehfa.Attributes; -using System.Runtime.InteropServices; -namespace Serehfa -{ - using static ArgHelpers; +namespace Serehfa; - [LispLibrary("scheme", "write")] - public static class Write +using static ArgHelpers; + +[LispLibrary("scheme", "write")] +public static class Write +{ + static Write() { - static Write() + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Console.OutputEncoding = Encoding.UTF8; - } + Console.OutputEncoding = Encoding.UTF8; } + } - /// - /// The newline method. This is a prime candidate for being moved to - /// a pure scheme definition. - /// - [LispExport("newline")] - public static object Newline(object[] args) - { - CheckNoArgs(args); + /// + /// The newline method. This is a prime candidate for being moved to + /// a pure scheme definition. + /// + [LispExport("newline")] + public static object Newline(object[] args) + { + CheckNoArgs(args); - Console.WriteLine(); + Console.WriteLine(); - return Undefined.Instance; - } + return Undefined.Instance; + } - /// - /// Display builtin. This is intended for user-readable output rather than - /// any machine readable round tripping. Printing out strings & chars should - /// display their raw form. All other objects is up to the implementation. - /// - /// This implementation calls `ToString` on the underlying .NET object and - /// uses that directly. - /// - [LispExport("display")] - public static object Display(object[] args) - { - var obj = UnpackArgs(args); + /// + /// Display builtin. This is intended for user-readable output rather than + /// any machine readable round tripping. Printing out strings & chars should + /// display their raw form. All other objects is up to the implementation. + /// + /// This implementation calls `ToString` on the underlying .NET object and + /// uses that directly. + /// + [LispExport("display")] + public static object Display(object[] args) + { + var obj = UnpackArgs(args); - var repr = GetDisplayRepresentation(obj); + var repr = GetDisplayRepresentation(obj); - Console.Write(repr); + Console.Write(repr); - return Undefined.Instance; - } + return Undefined.Instance; + } - /// - /// Write builtin. This is intended for round-trippable and machine - /// readable output. - /// - [LispExport("write")] - public static object WriteExternal(object[] args) - { - var obj = UnpackArgs(args); + /// + /// Write builtin. This is intended for round-trippable and machine + /// readable output. + /// + [LispExport("write")] + public static object WriteExternal(object[] args) + { + var obj = UnpackArgs(args); - var repr = GetExternalRepresentation(obj); + var repr = GetExternalRepresentation(obj); - Console.Write(repr); + Console.Write(repr); - return Undefined.Instance; - } + return Undefined.Instance; + } - public static string GetDisplayRepresentation(object o) => o switch - { - string s => s, - char c => c.ToString(), - _ => GetExternalRepresentation(o), - }; + public static string GetDisplayRepresentation(object o) => o switch + { + string s => s, + char c => c.ToString(), + _ => GetExternalRepresentation(o), + }; - public static string GetExternalRepresentation(object o) => o switch - { - bool b => b ? "#t" : "#f", - double d => d.ToString("G0"), - string s => EscapeString(s), - char c => char.IsLetterOrDigit(c) || char.IsPunctuation(c) ? - @"#\" + c : $@"#\x{Convert.ToUInt32(c):x4}", - null => "'()", - Func f => $"#", - object[] v => Vectors.GetExternalRepresentation(v), - byte[] v => ByteVectors.GetExternalRepresentation(v), - _ => o.ToString(), - }; - - private static string EscapeString(string s) + public static string GetExternalRepresentation(object o) => o switch + { + bool b => b ? "#t" : "#f", + double d => d.ToString("G0"), + string s => EscapeString(s), + char c => char.IsLetterOrDigit(c) || char.IsPunctuation(c) ? + @"#\" + c : $@"#\x{Convert.ToUInt32(c):x4}", + null => "'()", + Func f => $"#", + object[] v => Vectors.GetExternalRepresentation(v), + byte[] v => ByteVectors.GetExternalRepresentation(v), + _ => o.ToString(), + }; + + private static string EscapeString(string s) + { + var sb = new StringBuilder(); + sb.Append("\""); + foreach (var c in s) { - var sb = new StringBuilder(); - sb.Append("\""); - foreach (var c in s) + if (c == '\\' || c == '\"') + { + sb.AppendFormat(@"\{0}", c); + } + else if (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || c == ' ') { - if (c == '\\' || c == '\"') - { - sb.AppendFormat(@"\{0}", c); - } - else if (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || c == ' ') - { - sb.Append(c); - } - else - { - sb.AppendFormat(@"\x{0:x4};", Convert.ToUInt32(c)); - } + sb.Append(c); + } + else + { + sb.AppendFormat(@"\x{0:x4};", Convert.ToUInt32(c)); } - sb.Append("\""); - return sb.ToString(); } + + sb.Append("\""); + return sb.ToString(); } }