Исходники: Oyster.Units
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 05:55
Оценка:
UnitsDefinition.n:

[assembly: Oyster.Units.Macros.UnitsDefinition([
    // SI
    basisUnits (Si)
    (
        Mass,
        Length,
        Time,
        Temperature,
        CurrentStrength,
        LightIntensity,
        QuantityOfSubstance
    ),

    basisAliases (Si)
    (
        Area = (Length ^ 2),
        Volume = Area * Length,
        Velocity = Length / Time,
        Acceleration = Velocity / Time,
        AngularVelocity = Velocity,
        AngularAcceleration = Acceleration,
        Density = Mass / Volume,

        Force = Mass * Acceleration,
        SpecificGravity = Mass / (Length ^ 2) / (Time ^ 2),
        Pressure = SpecificGravity * Length,

        LinearMomentum = Mass * Velocity,
        MomentOfInertia = Mass * Area,

        Energy = Force * Length,
        Power = Energy / Time,

        DynamicViscosity = Mass / Length / Time,
        KinematicViscosity = DynamicViscosity,

        HeatCapacity = Energy / Temperature,
        Entropy = HeatCapacity,
        SpecificHeat = HeatCapacity / Mass,
        SpecificEntropy = SpecificHeat,

        Charge = Time * CurrentStrength,
        LinearDensityOfCharge = Charge / Length,
        SurfaceDensityOfCharge = Charge / Area,
        ElectricFluxDensity = SurfaceDensityOfCharge,
        PackedDensityOfCharge = Charge / Volume,

        Voltage = Power / CurrentStrength,
        ElectricForce = Force / CurrentStrength,
        Resistance = Voltage / CurrentStrength,
        SpecificResistance = Resistance * Length,

        Permittance = Time / Resistance,

        CurrentDensity = CurrentStrength / (Length ^ 2)
    ),

    // CGS
    units (Cgs)
    (
        Mass - 1.0 / 1000.0,
        Length - 1.0 / 100.0,
        Time,
        Temperature,
        CurrentStrength - 1.0 / 3000000000.0,
        LightIntensity,
        QuantityOfSubstance
    ),

    // Other units
    units (_)
    (
        HorsePower = Power - 1471.0 / 2.0
    )
])]
Исходники: Oyster.Units.Macros
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 05:55
Оценка:
CompileTimeInfo.n:

using System.Collections.Generic;

namespace Oyster.Units.Macros
{
    /// Stores compile-time information for UnitsDefinition macro
    module CompileTimeInfo
    {
        /// List of basis unit names in correct order
        public mutable BasisUnits : list[string] = [];

        /// List of all common units (including basis ones)
        public mutable CommonUnits : list[string] = [];

        /// Map of common unit powers
        public PowersMap : Dictionary[string, list[int]] = Dictionary();
    }
}

IUnit.n:

namespace Oyster.Units
{
    /// Interface for all units
    public interface IUnit {}
}

NormCoefAttribute.n:

using System;

namespace Oyster.Units
{
    /// Unit normalization coefficient attribute
    [AttributeUsage(AttributeTargets.Class)]
    public class NormCoefAttribute : Attribute
    {
        public NormCoef : double;

        public this (normCoef : double)
        {
            NormCoef = normCoef
        }
    }
}

OpMacros.n:

using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Internal;
using Nemerle.Macros;

namespace Oyster.Units.Macros
{
    /// Contains some operator-specific helper functionality
    module OpUtil
    {
        /// Used inside ariphmetic op macros
        public Body(
            ctx : Typer,
            lexpr : PExpr,
            rexpr : PExpr,
            opFun : PExpr * PExpr -> PExpr,
            bodyFun : TypeInfo * TypeInfo * double * double * list[int] * list[int] -> PExpr) : PExpr
        {
            match ((Util.GetExprType(ctx, lexpr), Util.GetExprType(ctx, rexpr)))
            {
                | (Some(ltype), Some(rtype)) =>
                    match ((Util.ParseUnitSuffix(ltype), Util.ParseUnitSuffix(rtype)))
                    {
                        | (lpowers, rpowers) when lpowers.Length > 0 && rpowers.Length > 0 =>
                            def getCoef(t) { Util.GetUnitNormCoef(t).Value };
                            bodyFun(ltype, rtype, getCoef(ltype), getCoef(rtype), lpowers, rpowers)
                        | _ => opFun(lexpr, rexpr)
                    }
                | _ => opFun(lexpr, rexpr)
            }
        }

        /// Used inside + and - macros
        public AddSubBody(
            ctx : Typer,
            lexpr : PExpr,
            rexpr : PExpr,
            opName : string,
            opFun : PExpr * PExpr -> PExpr) : PExpr
        {
            Body(
                ctx,
                lexpr,
                rexpr,
                opFun,
                fun (ltype, _, lcoef, rcoef, lpowers, rpowers)
                {
                    if (lpowers.Equals(rpowers))
                    {
                        def ctorParam = opFun(
                            <[ $lexpr.Value ]>,
                            <[ double.op_Multiply($rexpr.Value, $(rcoef / lcoef : double)) ]>);
                        <[ $(Util.UseSiteExpr(ltype.FullName))($ctorParam) ]>
                    }
                    else
                    {
                        Message.FatalError(
                            $"Expression { $lexpr [$opName] $rexpr } can't be compiled "
                             "because units are having different dimensions.")
                    }
                })
        }

        /// Used inside * and / macros
        public MulDivBody(
            ctx : Typer,
            lexpr : PExpr,
            rexpr : PExpr,
            opFun : PExpr * PExpr -> PExpr,
            powersFun : int * int -> int,
            coefFun : double * double -> double) : PExpr
        {
            Body(
                ctx,
                lexpr,
                rexpr,
                opFun,
                fun (_, _, lcoef, rcoef, lpowers, rpowers)
                {
                    def powers = List.Map2(lpowers, rpowers, powersFun);
                    def t = TypeGenerator.GenerateUnitType(ctx.Env, "", 1.0, powers);
                    def opExpr = opFun(<[ $lexpr.Value ]>, <[ $rexpr.Value ]>);
                    <[ $(t.Name : usesite)(double.op_Multiply($opExpr, $(coefFun(lcoef, rcoef) : double))) ]>
                })
        }
    }


    /// Units addition macro-operator
    macro @+(lexpr, rexpr)
    {
        OpUtil.AddSubBody(ImplicitCTX(), lexpr, rexpr, "+", Util.AddExpr)
    }

    /// Units subtraction macro-operator
    macro @-(lexpr, rexpr)
    {
        OpUtil.AddSubBody(ImplicitCTX(), lexpr, rexpr, "-", Util.SubExpr)
    }

    /// Units multiply macro-operator
    macro @*(lexpr, rexpr)
    {
        OpUtil.MulDivBody(ImplicitCTX(), lexpr, rexpr, Util.MulExpr, _ + _, _ * _)
    }

    /// Units divide macro-operator
    macro @/(lexpr, rexpr)
    {
        OpUtil.MulDivBody(ImplicitCTX(), lexpr, rexpr, Util.DivExpr, _ - _, _ / _)
    }
}

TypeGenerator.n:

using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;

using NST = Nemerle.Compiler.NamespaceTree;

namespace Oyster.Units.Macros
{
    /// Contains type generation methods
    module TypeGenerator
    {
        /// Contains already initialized environments
        mutable InitedEnvs : list[GlobalEnv] = [];

        /// Generates new unit type
        public GenerateUnitType(env : GlobalEnv, name : string, coef : double, powers : list[int]) : TypeBuilder
        {
            def nameIsEmpty = name == "";

            // Form type name
            def n = if (nameIsEmpty) Macros.NewSymbol("Unit") else Macros.UseSiteSymbol(name);

            // Try to find this type before creating it
            when (env.LookupType([ n.Id ]).HasValue)
            {
                Message.FatalError($"Type $(env.CurrentNamespace).$name already exists")
            };

            def ifaceName = Util.UseSiteExpr(GetUnitInterface(powers).FullName);
            def t = env.Define(<[ decl:
                [NormCoef($(coef : double))]
                public struct $(n : name)/*['a]*/ : $ifaceName //where 'a : $(ifaceName : name)
                {
                    _value : double;

                    public this(value : double)
                    {
                        _value = value
                    }
                    public this(unit : $ifaceName)
                    {
                        _value = unit.Value * unit.NormCoef / $(coef : double)
                    }

                    public Value : double
                    {
                        get { _value }
                    }
                    public NormCoef : double
                    {
                        get { $(coef : double) }
                    }

                    override public ToString() : string
                    {
                        _value.ToString()
                    }

                    static public @:>(unit : $(n : name)) : double
                    {
                        unit._value
                    }
                    static public @:(value : double) : $(n : name)
                    {
                        $(n : name)(value)
                    }
                    // TODO : Type conversion

                    static public @++(unit : $(n : name)) : $(n : name)
                    {
                        $(n : name)(unit.Value + 1)
                    }
                    static public @--(unit : $(n : name)) : $(n : name)
                    {
                        $(n : name)(unit.Value - 1)
                    }
                    static public @+(unit : $(n : name)) : $(n : name)
                    {
                        unit
                    }
                    static public @-(unit : $(n : name)) : $(n : name)
                    {
                        $(n : name)(0 - unit.Value)
                    }
                }
            ]>);

            // Define all simple arithmetic operations
            def defineSimpleOp(opName, valueType, opFun, isLeft)
            {
                mutable args = [ <[ parameter: value : $valueType ]>, <[ parameter: unit : $(n : name) ]> ];
                mutable opArgs = [ <[ value ]>, <[ unit.Value ]> ];
                when (!isLeft)
                {
                    args = args.Reverse();
                    opArgs = opArgs.Reverse();
                };
                
                t.Define(<[ decl:
                    static public $(opName.name : name)( .. $args ) : $(n : name)
                    {
                        $(n : name)($(opFun(opArgs.Head, opArgs.Tail.Head)))
                    }
                ]>)
            };
            def defineOp(opName, opFun)
            {
                [ true, false ].Iter(defineSimpleOp(opName, <[ double ]>, opFun, _))
            };

            defineOp(<[ @+ ]>, Util.AddExpr);
            defineOp(<[ @- ]>, Util.SubExpr);
            defineOp(<[ @* ]>, Util.MulExpr);
            defineOp(<[ @/ ]>, Util.DivExpr);
            
            t.Compile();
            t
        }

        /// Generates or gets unit interface for given powers list
        GetUnitInterface(powers : list[int]) : TypeInfo
        {
            def env = Util.UnitsEnv;

            def ifaceName = $"$(Util.UnitInterfacePrefix)$(Util.GetUnitSuffix(powers))";
            match (env.LookupType([ ifaceName ]))
            {
                | Some(t) => t
                | _ =>
                    // Create new interface
                    def ifaceName = Macros.UseSiteSymbol(ifaceName);
                    def t = env.Define(<[ decl:
                        public interface $(ifaceName : name) : IUnit
                        {
                            // We must declare all members here because of compiler bug
                            Value : double { get; }
                            NormCoef : double { get; }
                        }
                    ]>);
                    t.Compile();
                    t
            }
        }
    }
}

UnitsDefinition.n:

using System;
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;

namespace Oyster.Units.Macros
{
    using CTI = CompileTimeInfo;

    /// Assembly macro-attribute used to define unit types with custom DSL.
    [MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Assembly)]
    macro UnitsDefinition(defExpr)
    {
        // Parse top-level declaration elements
        match (defExpr)
        {
            | <[ [ .. $unitDefs ] ]> =>
                // Parse every unit definition block
                foreach (<[ $blockName ($nsName) ( .. $units ) ]> in unitDefs)
                {
                    // Define some settings basing on block name
                    def (addToBasis, addToAliases) =
                        match (blockName)
                        {
                            | <[ basisUnits ]> => (true, true)
                            | <[ basisAliases ]> => (false, true)
                            | <[ units ]> => (false, false)
                            | _ => Message.FatalError($"Expected block name, got $blockName")
                        };

                    // Extract namespace name
                    def nsName =
                        match (nsName)
                        {
                            | <[ _ ]> => ""
                            | <[ $(n : name) ]> => n.Id
                            | _ => Message.FatalError($"Expected namespace name, got $nsName")
                        };

                    // Proceed with units. unitsList will contain tuples (name, coef, [powers]) at the end
                    mutable unitsList = [];
                    foreach (unitDef in units)
                    {
                        def parseUnit(unit)
                        {
                            | <[ $(unitName : name) = $aliasDef - $coefDef ]> =>
                                def unitName = unitName.Id;

                                // Gather powers list
                                mutable havingDefinedAlias = true;
                                def powers =
                                    match (aliasDef)
                                    {
                                        | <[ _ ]> =>
                                            havingDefinedAlias = false;
                                            if (addToBasis) [] else CTI.PowersMap[unitName]
                                        
                                        | _ =>
                                            def parseAlias(alias)
                                            {
                                                | <[ ($(n : name) ^ $(k : int)) ]> => CTI.PowersMap[n.Id].Map(_ * k)

                                                | <[ $e * ($n ^ $k) ]> =>
                                                    List.Map2(parseAlias(e), parseAlias(<[ ($n ^ $k) ]>), _ + _)

                                                | <[ $e / ($n ^ $k) ]> =>
                                                    List.Map2(parseAlias(e), parseAlias(<[ ($n ^ $k) ]>), _ - _)

                                                | <[ $(n : name) ]> => parseAlias(<[ ($(n : name) ^ 1) ]>)

                                                | <[ $e * $(n : name) ]> => parseAlias(<[ $e * ($(n : name) ^ 1) ]>)

                                                | <[ $e / $(n : name) ]> => parseAlias(<[ $e / ($(n : name) ^ 1) ]>)

                                                | _ => Message.FatalError($"Expected unit alias, got $aliasDef")
                                            };
                                            def powers = parseAlias(aliasDef);

                                            // Global aliases must be added immediately
                                            when (addToAliases)
                                            {
                                                CTI.PowersMap[unitName] = powers
                                            };

                                            powers
                                    };

                                // Parse coefficient
                                def coef =
                                    match (coefDef)
                                    {
                                        | <[ _ ]> => if (addToAliases || !havingDefinedAlias) 1.0 else double.NaN
                                        | _ =>
                                            def parseCoef(coef)
                                            {
                                                | <[ $(d : double) ]> => d
                                                | <[ $e * $(d : double) ]> => parseCoef(e) * d
                                                | <[ $e / $(d : double) ]> => parseCoef(e) / d
                                                | _ => Message.FatalError($"Expected unit normalization coefficient, got $coefDef")
                                            };
                                            parseCoef(coefDef)
                                    };

                                (unitName, coef, powers)

                            | <[ $(unitName : name) - $coefDef ]> => parseUnit(<[ $(unitName : name) = _ - $coefDef ]>)

                            | <[ $(unitName : name) = $aliasDef ]> => parseUnit(<[ $(unitName : name) = $aliasDef - _ ]>)
                                    
                            | <[ $_ - $_ ]> => Message.FatalError($"Expected unit definition, got $unitDef (transformed into $unit)")

                            | <[ $e ]> => parseUnit(<[ $e - _ ]>)
                        };
                        unitsList ::= parseUnit(unitDef)
                    };
                    unitsList = unitsList.Reverse();

                    def names = unitsList.Map(fun(n, _, _) { n });

                    // Maybe initialize basis units list
                    when (addToBasis)
                    {
                        // Calculate powers for basis types
                        unitsList = unitsList.Map(
                            fun(n, coef, _)
                            {
                                (n, coef, unitsList.Map(fun(n2, _, _) { if (n == n2) 1 else 0 }))
                            });

                        // Add all powers to hash
                        unitsList.Iter(fun(n, _, powers) { CTI.PowersMap[n] = powers });

                        // Initialize BasisUnits
                        CTI.BasisUnits = names
                    };

                    // Maybe add units to global aliases list
                    when (addToAliases)
                    {
                        CTI.CommonUnits = CTI.CommonUnits.Append(names)
                    };

                    // Generate all new types for units in given NS.
                    // Maybe also generate additional aliases if all basis units are declared
                    mutable basisCoef = [];
                    when (!addToAliases && CTI.BasisUnits.ForAll(names.Contains))
                    {
                        def additionalNames = CTI.CommonUnits.Filter(fun(n) { !names.Contains(n) });
                        unitsList = unitsList.Append(additionalNames.Map(fun(n) { (n, double.NaN, CTI.PowersMap[n]) }));

                        // Fill local coef hash
                        basisCoef = CTI.BasisUnits.Map(fun(n) { unitsList.Find(fun(n2, _, _) { n == n2 }).Value[1] })
                    };

                    def env = Util.GetUnitsEnv(nsName);

                    foreach ((unitName, coef, powers) in unitsList)
                    {
                        def coef =
                            if (double.IsNaN(coef))
                            {
                                // Try to obtain coefficient automatically
                                List.FoldLeft2(basisCoef, powers, 1.0, fun(c, p : int, r) { Math.Pow(c, p) * r })
                            }
                            else
                            {
                                coef
                            };

                        // Generate type for given namespace
                        _ = TypeGenerator.GenerateUnitType(env, unitName, coef, powers)
                    }
                }
            | _ => Message.FatalError($"Expected comma-separated unit declaration blocks, got $defExpr")
        }
    }
}

Util.n:

using System;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Utility;

namespace Oyster.Units
{
    /// Contains different utilitary fields/methods
    module Util
    {
        // Some constants
        public UnitsNS = "Oyster.Units";
        public UnitInterfacePrefix = "IUnit_";
        public UnitInterfaceFullPrefix : string = $"$UnitsNS.$UnitInterfacePrefix";

        /// Units environment
        public UnitsEnv : GlobalEnv = GetUnitsEnv("");


        /// Creates new GlobalEnv for units global namespace
        public GetUnitsEnv(nsName : string) : GlobalEnv
        {
            def nsName = if (nsName == "") "" else $".$nsName";
            GlobalEnv($"$UnitsNS$nsName&$UnitsNS&&")
        }

        /// Generates PExpr for dot-separated names
        public UseSiteExpr(name : string) : PExpr
        {
            def prepareExpr(l)
            {
                | h :: [] => <[ $(h : usesite) ]>
                | h :: t => <[ $(prepareExpr(t)).$(h : usesite) ]>
                | _ => Message.FatalError($"Expecting dot-separated class name, got $name")
            };
            prepareExpr(GetTypeNameList(name).Reverse())
        }

        /// Returns namespace path list for given full dot-separated type name
        public GetTypeNameList(name : string) : list[string]
        {
            NString.Split(name, '.')
        }

        /// Generates unit interface suffix basing on base unit powers
        public GetUnitSuffix(powers : list[int]) : string
        {
            powers.ToString("_")
        }

        /// Parses unit interface suffix
        public ParseUnitSuffix(t : TypeInfo) : list[int]
        {
            def isIfaceName(s) { s.StartsWith(UnitInterfaceFullPrefix) };
            def name =
                if (t is TypeBuilder)
                {
                    // Get for newly generated type
                    match (t.GetSuperTypes().Find( fun(super) { isIfaceName(super.TypeInfo.FullName) }))
                    {
                        | Some(iface) => iface.TypeInfo.Name
                        | _ => ""
                    }
                }
                else
                {
                    // Get for existing type
                    def iface = Array.Find(t.SystemType.GetInterfaces(), fun (i) { isIfaceName(i.FullName) });
                    if (iface != null) iface.Name else ""
                };
            if (name == "") [] else NString.Split(name, '_').Tail.Map(int.Parse)
        }

        /// Returns PExpr type
        public GetExprType(ctx : Typer, expr : PExpr) : option[TypeInfo]
        {
            match (ctx.TypeExpr(expr).ty.Hint)
            {
                | Some(t) => Some(t.TypeInfo)
                | _ => None()
            }
        }

        /// Returns normalization coefficient if type is concrete unit type
        public GetUnitNormCoef(t : TypeInfo) : option[double]
        {
            | t is TypeBuilder =>
                // Get attribute using Nemerle approach
                match (t.FindAttribute(GlobalEnv.Core.LookupType(GetTypeNameList($"$UnitsNS.NormCoefAttribute")).Value))
                {
                    | Some(<[ NormCoef($(coef : double)) ]>) => Some(coef)
                    | _ => None()
                }
            | _ =>
                // "Usual" attribute gathering
                match (Attribute.GetCustomAttribute(t.SystemType, typeof(NormCoefAttribute)))
                {
                    | null => None()
                    | attr => Some((attr :> NormCoefAttribute).NormCoef)
                }
        }

        // Different expression generators
        public AddExpr(lexpr : PExpr, rexpr : PExpr) : PExpr
        {
            <[ $lexpr + $rexpr ]>
        }
        public SubExpr(lexpr : PExpr, rexpr : PExpr) : PExpr
        {
            <[ $lexpr - $rexpr ]>
        }
        public MulExpr(lexpr : PExpr, rexpr : PExpr) : PExpr
        {
            <[ $lexpr * $rexpr ]>
        }
        public DivExpr(lexpr : PExpr, rexpr : PExpr) : PExpr
        {
            <[ $lexpr / $rexpr ]>
        }
    }
}
Re[2]: [Nemerle] Семантический контроль над размерностями
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 05:55
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Собсно, без value-типов временный незачет, ждем-с окончательной версии.


А вот и value-типы
Автор: Oyster
Дата: 10.04.06
. Только это ещё не окончательная версия, я надеюсь...
Re[2]: [Nemerle] Семантический контроль над размерностями
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 05:55
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Немного отдаёт неряшливостью, что внесистемные единицы помещены в систему Ext.

К>На то они и внесистемные...

Замечание учтено: Версия 0.02
Автор: Oyster
Дата: 10.04.06
.
Версия 0.03 - скажем "нет" боксингу :)
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 08:26
Оценка: 66 (4)
Не успел я выложить версию 0.02
Автор: Oyster
Дата: 10.04.06
, как подоспела следующая. В версии 0.03 использован workaround, предложенный разработчиками Nemerle для обхода бага и, как результат, я избавился от боксинга в конструкторе, т.е. теперь решение действительно на 100% на value-типах

Новую версию забираем тут: Oyster.Units.0.03.zip. Для сборки надо использовать Nemerle билд r6176 — не ниже (как и для предыдущей версии).

PS: Исходники текстом не выкладываю — они почти не изменились.
Re: Версия 0.03 - скажем "нет" боксингу :)
От: Аноним  
Дата: 10.04.06 08:52
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Новую версию забираем тут: Oyster.Units.0.03.zip. Для сборки надо использовать Nemerle билд r6176 — не ниже (как и для предыдущей версии).


Для того, чтобы проинсталлировать билд, что должно уже стоять на машине? Необходимо ли наличие питона, antlr и ряда прочих вещей, которые проверяются в ./configure? Какую версию make.exe следует использовать?
Re[2]: Версия 0.03 - скажем "нет" боксингу :)
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 08:58
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Для того, чтобы проинсталлировать билд, что должно уже стоять на машине? Необходимо ли наличие питона, antlr и ряда прочих вещей, которые проверяются в ./configure? Какую версию make.exe следует использовать?


У меня WinXP и я просто поставил cygwin, как советуют сами разработчики. Поэтому я не знаю, что ещё надо ставить — ставил почти всё по умолчанию (кроме make — см. ниже).

Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.
Re[3]: установка Nemerle
От: Аноним  
Дата: 10.04.06 10:00
Оценка:
Здравствуйте, Oyster, Вы писали:

O>У меня WinXP и я просто поставил cygwin, как советуют сами разработчики. Поэтому я не знаю, что ещё надо ставить — ставил почти всё по умолчанию (кроме make — см. ниже).


O>Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.


Спасибо.

Случаем не встречались с такой проблемой: make останавливается на 3-ем stage после компиляции ncc.exe с ошибкой
*** No rule to make target '../../ncc/out.stage/', needed by 'Nemerle.dll'. Stop.
Re[4]: установка Nemerle
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 11:05
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Случаем не встречались с такой проблемой: make останавливается на 3-ем stage после компиляции ncc.exe с ошибкой

А>*** No rule to make target '../../ncc/out.stage/', needed by 'Nemerle.dll'. Stop.

Нет, у меня всегда компилится нормально... Можно попробовать отписать им на форум.
Re[6]: [Nemerle] Семантический контроль над размерностями
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 20:26
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:

VK>Но есть идея и более простая. И макрос, и оператор можно зарегистрировать вручную через API компилятора(см. модуль MacroRegistry). Макрос это по сути экземпляр некого класса, реализовывающего интерфейс IMacro. Нужно просто написать собственную реализацию IMacro вручную(т.е. не использовать встроенную в компилятор генерацию этого класса), которая в зависимости от того как ее инициализируют будет вести себя как разные макросы(т.е. с разными именами и генерировать различный код).


Как ты уже знаешь, эта идея мне понравилась. В общем, я начал думать о том, как реализовать unit-алиасы с её помощью и столкнулся с маленькой проблемкой. Дело в том, что в текущей версии библиотеки
Автор: Oyster
Дата: 10.04.06
unit-типы можно определять как в той же сборке, где они используются, так и в другой сборке, и я хочу сохранить такое поведение. Вот в варианте с другой сборкой и возникает проблема — надо как-то создать и загеристрировать макросы при загрузке сборки компилятором.

Я думал над этой проблемой и пришёл к такому вот решению:

  1. Unit-алиасы (такие как kg — клиограммы — или m — метры, — например) сохраняются в неком атрибуте уровня сборки (или в любом другом хранилище в сборке с unit-типами).
  2. Также в этой сборке создаётся псевдо-макрос, который ничего не умеет и в конструкторе которого создаются и регистрируются макросы для unit-алиасов. На сборку цепляется ContainsMacroAttribute и, как результат, конструктор этого псевдо-макроса выполняется при загрузке сборки LibraryLoader-ом.

Конечно, возможен и другой вариант — генерация классов макросов для unit-алиасов, но этого не хочется делать из-за желания использовать код повторно.

Собственно, мой вопрос звучит так — можно ли то же самое сделать как-то иначе? Т.е. существует ли какой-нибудь другой способ выполнить код при загрузке сборки кроме ContainsMacroAttribute и конструктора макроса?
Re[7]: [Nemerle] Семантический контроль над размерностями
От: Oyster Украина https://github.com/devoyster
Дата: 10.04.06 21:15
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Конечно, возможен и другой вариант — генерация классов макросов для unit-алиасов, но этого не хочется делать из-за желания использовать код повторно.


На самом деле, мы можем просто создавать типы для макросов, регистрировать их ручками, если в той же сборке, и не мучаться с добавлением ещё каких-то вспомогательных атрибутов (кроме [ContainsMacro] и [Operator]). Естественно, это возможно только при условии, если мы можем из макроса добавить атрибуты сборке — я ещё не разбирался с этим вопросом. Кстати, это утверждение также справедливо для варианта из предыдущего сообщения.

При таком подходе снова встаёт вопрос — а могу ли я просто создать новый макрос внутри макроса, используя знакомый мне синтаксис macro и не переопределяя IMacro вручную?
Версия 0.04
От: Oyster Украина https://github.com/devoyster
Дата: 14.04.06 05:43
Оценка: 54 (3)
Ну вот и следующий билд библиотеки подоспел: Oyster.Units.0.04.zip (собирать на Nemerle версии r6192, не ниже).

В этом билде разработчики языка исправили кое-какие баги, поэтому код библиотеки тоже был исправлен местами. Но самое главное, конечно, не это. Самое главное то, что этот билд добавляет возможность работы с физическими литералами, о которых в этом топике уже писали. В общем, теперь можно писать код вроде такого:

def m3 = 1 g;
def m4 = Si.Mass(m1);

WriteLine($"Mass in SI: $m4, in CGS: $m3");

def x1 = Si.Area(1 cm * 10 m);

WriteLine($"Area of 1 cm * 10 m = $x1 m")

1 g, 1 cm и 10 m из примера выше — это как раз физические литералы. Задаются они непосредственно в DSL вот таким вот образом:

basisUnits (Si)
(
    Mass[ kg ],
    Length[ m ],
    Time[ sec ],
    Temperature[ K ],
    CurrentStrength[ A ],
    LightIntensity,
    QuantityOfSubstance
)

Т.е. после любого имени юнита можно указать имя литерала в квадратных скобках (уникальное в пределах данного описания). При этом в библиотеку, в которой находится описание юнитов, будет скомпилирован соответствующий макро-оператор, доступный при подключении пространства имён Oyster.Units.Macros.

У решения всё равно есть некоторые недостатки:


Тем не менее, все эти недостатки достаточно невелики и не мешают пользоваться библиотекой.


В заключение хочу сказать, что библиотека подобралась к своему логическому завершению и вряд ли будет развиваться дальше. Возможно, будут исправляться ошибки, но не более того.
Re[2]: [Nemerle] Семантический контроль над размерностями
От: Oyster Украина https://github.com/devoyster
Дата: 14.04.06 05:46
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Это было бы такое WOW , что вполне возможно, я бы прыгнул на Немерле.


Так прыгнул бы или нет?
Автор: Oyster
Дата: 14.04.06
Re[3]: [Nemerle] Семантический контроль над размерностями
От: vdimas Россия  
Дата: 14.04.06 09:10
Оценка:
Здравствуйте, Oyster, Вы писали:


V>>Это было бы такое WOW , что вполне возможно, я бы прыгнул на Немерле.


O>Так прыгнул бы или нет?
Автор: Oyster
Дата: 14.04.06


Доделываю хвосты и прыгаю
Нельзя же бросать текучку...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Версия 0.03 - скажем "нет" боксингу :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.04.06 23:54
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.


Стандартного мэйка нет в природе.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Версия 0.04
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.04.06 23:54
Оценка: +2
Здравствуйте, Oyster, Вы писали:

В общем, хотя реально сама библиотека будет бесполезна для 99% программистов и проектов, но 3 огромные задачи ты ею решил:
1. Нашел кучу багов в компиляторе.
2. Создал изумительный пример разработки DSL. Очень советую, кстати, запостить его в форум Немерла посвященный примерам. Можно со ссылкой на С++-ный аналог.
3. Доказал приемущество макросов над шаблонным метапрограммированием и вообще их гибкость.

... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: [Nemerle] Семантический контроль над размерностями
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.04.06 00:02
Оценка:
Здравствуйте, vdimas, Вы писали:

O>>Так прыгнул бы или нет?
Автор: Oyster
Дата: 14.04.06


V>Доделываю хвосты и прыгаю

V>Нельзя же бросать текучку...

Ну, вот мы и тебя "проникли".
Хотя доделывать хвосты можно вечно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Версия 0.03 - скажем "нет" боксингу :)
От: Oyster Украина https://github.com/devoyster
Дата: 16.04.06 07:51
Оценка:
Здравствуйте, VladD2, Вы писали:

O>>Знаю точно, что нужен gmake, а не стандартный make, — это было написано где-то в доках.

VD>Стандартного мэйка нет в природе.

Да, глупость сказал... Я имел в виду, "нужен не тот make, который ставится с cygwin по умолчанию, а gmake".
Re[2]: Версия 0.04
От: Oyster Украина https://github.com/devoyster
Дата: 16.04.06 07:58
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>2. Создал изумительный пример разработки DSL. Очень советую, кстати, запостить его в форум Немерла посвященный примерам. Можно со ссылкой на С++-ный аналог.


Да, это я как раз и хотел сделать. Вот найду время, поперевожу некоторые комменты на англицкий, получу разрешение у CrystaX и сделаю, мабуть.
Re[3]: Версия 0.04
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.04.06 17:38
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Да, это я как раз и хотел сделать. Вот найду время, поперевожу некоторые комменты на англицкий, получу разрешение у CrystaX и сделаю, мабуть.


Давай. Зело полезное дело!
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.