Click here to Skip to main content
15,886,639 members
Articles / Programming Languages / C#

Lua Interpreter

Rate me:
Please Sign up or sign in to vote.
4.89/5 (32 votes)
22 Sep 2012MIT4 min read 99.4K   3K   85  
A Lua interpreter is implemented in C#. It allows to write Lua extensions in C# and call the extensions in Lua code.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Language.Lua.Library
{
    public static class MathLib
    {
        public static void RegisterModule(LuaTable enviroment)
        {
            LuaTable module = new LuaTable();
            RegisterFunctions(module);
            enviroment.SetNameValue("math", module);
        }

        public static void RegisterFunctions(LuaTable module)
        {
            module.SetNameValue("huge", new LuaNumber(double.MaxValue));
            module.SetNameValue("pi", new LuaNumber(Math.PI));
            module.Register("abs", abs);
            module.Register("acos", acos);
            module.Register("asin", asin);
            module.Register("atan", atan);
            module.Register("atan2", atan2);
            module.Register("ceil", ceil);
            module.Register("cos", cos);
            module.Register("cosh", cosh);
            module.Register("deg", deg);
            module.Register("exp", exp);
            module.Register("floor", floor);
            module.Register("fmod", fmod);
            module.Register("log", log);
            module.Register("log10", log10);
            module.Register("max", max);
            module.Register("min", min);
            module.Register("modf", modf);
            module.Register("pow", pow);
            module.Register("rad", rad);
            module.Register("random", random);
            module.Register("randomseed", randomseed);
            module.Register("sin", sin);
            module.Register("sinh", sinh);
            module.Register("sqrt", sqrt);
            module.Register("tan", tan);
            module.Register("tanh", tanh);
        }

        public static LuaValue abs(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Abs(number.Number));
        }

        public static LuaValue acos(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Acos(number.Number));
        }

        public static LuaValue asin(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Asin(number.Number));
        }

        public static LuaValue atan(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Atan(number.Number));
        }

        public static LuaValue atan2(LuaValue[] values)
        {
            var numbers = CheckArgs2(values);
            return new LuaNumber(Math.Atan2(numbers.Item1, numbers.Item2));
        }

        public static LuaValue ceil(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Ceiling(number.Number));
        }

        public static LuaValue cos(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Cos(number.Number));
        }

        public static LuaValue cosh(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Cosh(number.Number));
        }

        public static LuaValue deg(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(number.Number * 180 / Math.PI);
        }

        public static LuaValue exp(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Exp(number.Number));
        }

        public static LuaValue floor(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Floor(number.Number));
        }

        public static LuaValue fmod(LuaValue[] values)
        {
            var numbers = CheckArgs2(values);
            return new LuaNumber(Math.IEEERemainder(numbers.Item1, numbers.Item2));
        }

        public static LuaValue log(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Log(number.Number));
        }

        public static LuaValue log10(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Log10(number.Number));
        }

        public static LuaValue max(LuaValue[] values)
        {
            return new LuaNumber(values.Max(v => (v as LuaNumber).Number));
        }

        public static LuaValue min(LuaValue[] values)
        {
            return new LuaNumber(values.Min(v => (v as LuaNumber).Number));
        }

        public static LuaValue modf(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            double integer = Math.Floor(number.Number);
            return new LuaMultiValue(new LuaNumber[]
                {
                 new LuaNumber(integer),
                 new LuaNumber(number.Number - integer)
                }
            );
        }

        public static LuaValue pow(LuaValue[] values)
        {
            var numbers = CheckArgs2(values);
            return new LuaNumber(Math.Pow(numbers.Item1, numbers.Item2));
        }

        public static LuaValue rad(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(number.Number * Math.PI / 180);
        }

        static Random randomGenerator = new Random();
        public static LuaValue random(LuaValue[] values)
        {
            if (values.Length == 0)
            {
                return new LuaNumber(randomGenerator.NextDouble());
            }
            else if (values.Length == 1)
            {
                LuaNumber number1 = values[0] as LuaNumber;
                return new LuaNumber(randomGenerator.Next((int)number1.Number));
            }
            else
            {
                var numbers = CheckArgs2(values);
                return new LuaNumber(randomGenerator.Next((int)numbers.Item1, (int)numbers.Item2));
            }
        }

        public static LuaValue randomseed(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            randomGenerator = new Random((int)number.Number);
            return number;
        }

        public static LuaValue sin(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Sin(number.Number));
        }

        public static LuaValue sinh(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Sinh(number.Number));
        }

        public static LuaValue sqrt(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Sqrt(number.Number));
        }

        public static LuaValue tan(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Tan(number.Number));
        }

        public static LuaValue tanh(LuaValue[] values)
        {
            LuaNumber number = CheckArgs(values);
            return new LuaNumber(Math.Tanh(number.Number));
        }

        private static LuaNumber CheckArgs(LuaValue[] values)
        {
            if (values.Length >= 1)
            {
                LuaNumber number = values[0] as LuaNumber;
                if (number != null)
                {
                    return number;
                }
                else
                {
                    throw new LuaError("bad argument #1 to 'abs' (number expected, got {0})", values[0].GetTypeCode());
                }
            }
            else
            {
                throw new LuaError("bad argument #1 to 'abs' (number expected, got no value)");
            }
        }

        private static Tuple<double, double> CheckArgs2(LuaValue[] values)
        {
            if (values.Length >= 2)
            {
                LuaNumber number1 = values[0] as LuaNumber;
                if (number1 == null)
                {
                    throw new LuaError("bad argument #1 to 'abs' (number expected, got {0})", values[0].GetTypeCode());
                }

                LuaNumber number2 = values[1] as LuaNumber;
                if (number2 == null)
                {
                    throw new LuaError("bad argument #2 to 'abs' (number expected, got {0})", values[1].GetTypeCode());
                }

                return Tuple.Create(number1.Number, number2.Number);
            }
            else
            {
                throw new LuaError("bad argument #1 to 'abs' (number expected, got no value)");
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Architect YunCheDa Hangzhou
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions