diff --git a/Makefile b/Makefile index 1a07a6c4..4010c7d3 100644 --- a/Makefile +++ b/Makefile @@ -40,6 +40,7 @@ SBCL = sbcl HC = ghc EC = ec JAVAC = javac +DOTNET = dotnet HCFLAGS = -dynamic -Wall -Werror -O3 HCLIBDIR = haskell/Mainlib HCLIBS = $(wildcard $(HCLIBDIR)/*.hs) @@ -54,12 +55,13 @@ PASCALS = $(wildcard pascal/*.pp) # LISPS = $(wildcard lisp/*.lisp) HASKELLS = $(wildcard haskell/*.hs) JAVAS = $(wildcard java/*.java) +CSHARPS = $(subst /Program.cs,.cs,$(wildcard csharp/*/Program.cs)) # Eiffel doesn't work, this may help: https://github.com/eiffel-docker/eiffel/issues/3 # EIFFELS = eiffel/application.e GOS = $(wildcard go/cmd/*/main.go) # I can't figure out how to install Ada on macOS with Homebrew :( # ADAS = $(wildcard ada/*.adb) -ASMS = $(subst ada/,asm/ada-,$(subst pascal/,asm/pascal-,$(subst eiffel/,asm/eiffel-,$(subst go/cmd/,asm/go-,$(subst haskell/,asm/haskell-,$(subst java/,asm/java-,$(subst lisp/,asm/lisp-,$(subst rust/,asm/rust-,$(subst cpp/,asm/cpp-,${CPPS:.cpp=.asm} ${RUSTS:.rs=.asm} ${LISPS:.lisp=.asm} ${HASKELLS:.hs=.asm} ${GOS:/main.go=.asm} ${JAVAS:.java=.asm} ${EIFFELS:.e=.asm} ${PASCALS:.pp=.asm} ${ADAS:.adb=.asm}))))))))) +ASMS = $(subst csharp/,asm/csharp-,$(subst ada/,asm/ada-,$(subst pascal/,asm/pascal-,$(subst eiffel/,asm/eiffel-,$(subst go/cmd/,asm/go-,$(subst haskell/,asm/haskell-,$(subst java/,asm/java-,$(subst lisp/,asm/lisp-,$(subst rust/,asm/rust-,$(subst cpp/,asm/cpp-,${CPPS:.cpp=.asm} ${RUSTS:.rs=.asm} ${LISPS:.lisp=.asm} ${HASKELLS:.hs=.asm} ${GOS:/main.go=.asm} ${JAVAS:.java=.asm} ${EIFFELS:.e=.asm} ${PASCALS:.pp=.asm} ${ADAS:.adb=.asm} ${CSHARPS:.cs=.asm})))))))))) BINS = $(subst asm/,bin/,${ASMS:.asm=.bin}) REPORTS = $(subst bin/,reports/,${BINS:.bin=.txt}) GOCACHE = /tmp/gocache @@ -112,6 +114,7 @@ install: Makefile echo "This is macOS, installing necessary components:" brew install fpc cppcheck sbcl go brew install --cask graalvm/tap/graalvm-ce-lts-java11 + brew install --cask dotnet-sdk elif [[ "$${OSTYPE}" == "linux-gnu"* ]]; then echo "This is Linux, installing necessary components:" apt-get -y update --fix-missing @@ -123,7 +126,8 @@ install: Makefile libyaml-dev libxml2-dev autoconf libc6-dev ncurses-dev \ automake libtool lsb-release \ gnat jq cppcheck bc fpc linux-tools-generic \ - ruby-full + ruby-full \ + dotnet-sdk-8.0 apt-get clean # see https://stackoverflow.com/a/76641565/187141 rm -f /usr/lib/python3.*/EXTERNALLY-MANAGED @@ -150,6 +154,7 @@ env: Makefile $(HC) --version $(FPC) -h >/dev/null $(JAVAC) --version + $(DOTNET) --version if [ -n "$(LISPS)" ]; then $(SBCL) --version; fi if [ -n "$(EIFFELS)" ]; then $(EC) --version; fi if [ -n "$(ADAS)" ]; then $(GNAT) --version; fi @@ -189,6 +194,9 @@ asm/eiffel-%.asm: eiffel/%.e | asm asm/go-%.asm: go/cmd/%/main.go | asm echo " no asm here" > "$@" +asm/csharp-%.asm: csharp/%/Program.cs | asm + echo " no asm here" > "$@" + asm/haskell-%.asm: haskell/%.hs $(HCLIBS) | asm source=$$( echo "$<" | sed 's/\.hs$$//' ) $(HC) $(HCFLAGS) -S $(HCLIBS) "$<" @@ -218,6 +226,11 @@ bin/eiffel-%.bin: eiffel/%.e | bin mv application "$@" chmod a+x "$@" +bin/csharp-%.bin: csharp/%/Program.cs | bin + cd "$$(dirname "$<")" + $(DOTNET) publish -c Release -r osx-x64 --self-contained + mv bin/Release/*/*/publish/* "../../$@" + bin/pascal-%.bin: pascal/%.pp | bin fpc "$<" "-FEbin" "-o$@" @@ -260,11 +273,11 @@ reports/%.txt: bin/%.bin asm/%.asm | reports if [ "$(FAST)" != "" ]; then break; fi seconds=$$(echo $${time} | cut -f1 -d.) if [ "$${seconds}" -gt "10" ]; then break; fi - if [ "$${seconds}" -gt "0" -a "$${cycles}" -ge "$(WANTED)" ]; then break; fi + if [ "$${seconds}" -gt "0" ] && [ "$${cycles}" -ge "$(WANTED)" ]; then break; fi echo "cycles=$${cycles}; time=$${time} -> too fast, need more cycles (attempt #$${attempt})..." cycles=$$(expr $${cycles} \* 2) if [ "$${cycles}" -gt "2147483647" ]; then break; fi - if [ "$${cycles}" -lt "$(WANTED)" -a "$${seconds}" -lt "1" ]; then cycles=$(WANTED); fi + if [ "$${cycles}" -lt "$(WANTED)" ] && [ "$${seconds}" -lt "1" ]; then cycles=$(WANTED); fi attempt=$$(expr $${attempt} + 1) done if [ "$$(uname)" == "Darwin" ]; then diff --git a/csharp/.gitignore b/csharp/.gitignore new file mode 100644 index 00000000..cbbd0b5c --- /dev/null +++ b/csharp/.gitignore @@ -0,0 +1,2 @@ +bin/ +obj/ \ No newline at end of file diff --git a/csharp/Objects/Objects.csproj b/csharp/Objects/Objects.csproj new file mode 100644 index 00000000..fdb4f2a3 --- /dev/null +++ b/csharp/Objects/Objects.csproj @@ -0,0 +1,9 @@ + + + Exe + net8.0 + enable + enable + true + + diff --git a/csharp/Objects/Program.cs b/csharp/Objects/Program.cs new file mode 100644 index 00000000..d272f43b --- /dev/null +++ b/csharp/Objects/Program.cs @@ -0,0 +1,169 @@ +// Copyright (c) 2022-2024 Yegor Bugayenko +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; + +class Program +{ + interface IBool + { + bool Get(); + } + + interface IInt + { + int Get(); + } + + class Integer : IInt + { + private readonly int value; + + public Integer(int v) + { + this.value = v; + } + + public int Get() + { + return this.value; + } + } + + class Less : IBool + { + private readonly IInt left; + private readonly IInt right; + + public Less(IInt l, IInt r) + { + this.left = l; + this.right = r; + } + + public bool Get() + { + return this.left.Get() < this.right.Get(); + } + } + + class Sub : IInt + { + private readonly IInt left; + private readonly IInt right; + + public Sub(IInt l, IInt r) + { + this.left = l; + this.right = r; + } + + public int Get() + { + return this.left.Get() - this.right.Get(); + } + } + + class Add : IInt + { + private readonly IInt left; + private readonly IInt right; + + public Add(IInt l, IInt r) + { + this.left = l; + this.right = r; + } + + public int Get() + { + return this.left.Get() + this.right.Get(); + } + } + + class If : IInt + { + private readonly IBool term; + private readonly IInt left; + private readonly IInt right; + + public If(IBool t, IInt l, IInt r) + { + this.term = t; + this.left = l; + this.right = r; + } + + public int Get() + { + if (this.term.Get()) + { + return this.left.Get(); + } + return this.right.Get(); + } + } + + class Fibo : IInt + { + private readonly IInt value; + + public Fibo(IInt v) + { + this.value = v; + } + + public int Get() + { + return new If( + new Less(this.value, new Integer(2)), + new Integer(1), + new Add( + new Fibo(new Sub(this.value, new Integer(1))), + new Fibo(new Sub(this.value, new Integer(2))) + ) + ).Get(); + } + } + + public static void Main(string[] args) + { + if (args.Length != 2) + { + Console.Write("Two args required: INPUT and CYCLES\n"); + return; + } + int total = 0; + int f = 0; + Integer input = new Integer(int.Parse(args[0])); + int cycles = int.Parse(args[1]); + for (int i = 0; i < cycles; ++i) + { + f = new Fibo(input).Get(); + total += f; + } + Console.Write( + string.Format( + "{0}-th Fibonacci number is {1}\nTotal is {2}\n", + input.Get(), f, total + ) + ); + } +}