не пойму проблемы
От: Аноним  
Дата: 23.08.13 14:07
Оценка:
макрос
  public macro razbor(y:PExpr)
  {
    <[y]>
  }

использую
razbor(<[def x=1;]>)

выдает ошибку
Re: не пойму проблемы
От: Аноним  
Дата: 23.08.13 14:12
Оценка:
Здравствуйте, Аноним, Вы писали:

А>макрос



А> public macro razbor(y:PExpr)

А> {
А> <[y]>
А> }

А>использую

А>razbor(<[def x=1;]>)

А>выдает ошибку


просто razbor({def x = 1}); не нужна цитата
Re: не пойму проблемы
От: CodingUnit Россия  
Дата: 23.08.13 14:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>макрос



А> public macro razbor(y:PExpr)

А> {
А> <[y]>
А> }

А>использую

А>razbor(<[def x=1;]>)

А>выдает ошибку


надо писать со ссылкой на выражение, <[ y ]> это просто переменная y области видимости раскрываемого макроса (то есть конечного кода), для правильного использования ссылок на другие выражения надо использовать сплайсы, так:


public macro razbor(y : PExpr)
{
   <[ $y ]>
}


или вообще вот так:

public macro razbor(y : PExpr)
{
   y
}



но если будете более сложное выражение использовать то конечно без сплайсов (ссылок на другие элементы в макросе) не обойтись

razbor(<[def x=1;]>) должен работать
Re[2]: не пойму проблемы
От: Аноним  
Дата: 23.08.13 14:43
Оценка:
Здравствуйте, CodingUnit, Вы писали:

Пока хочу разобрать текст и собрать заново.

примитивный
например
def x=1;
def t(x){x+1}
def y=t(x);
Re[3]: не пойму проблемы
От: CodingUnit Россия  
Дата: 23.08.13 14:58
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Пока хочу разобрать текст и собрать заново.


А>примитивный

А>например
А>def x=1;
А>def t(x){x+1}
А>def y=t(x);

Что значит разобрать текст? Вы имеет в виду выражение? Да для исследования выражений можно попытаться их разобрать макросами, исследуя дерево выражений, можно заглянуть и в Nemerle.Compiler.dll reflectorом и посмотреть состав классов производных от PExpr. Все выражения можно разбирать match оператором работая как с PExpr вариантом, так и с квазицитатами напрямую например:

def expr = <[ def x = 1 ]>;


match (expr)
{
  | PExpr.Define(pat, val) => // что то сделать с выражениями pattern и value из выражения def pattern = value
}


или


match (expr)
{
 | <[ def $x = $v]> => // аналогично первому варианту
}


Все значения в макросе проще смотреть через отладчик, для этого использовать функцию assert2(false) для вызова внешнего отладчика (студии)
Re[4]: не пойму проблемы
От: Аноним  
Дата: 23.08.13 16:09
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Все значения в макросе проще смотреть через отладчик, для этого использовать функцию assert2(false) для вызова внешнего отладчика (студии)


Это я знаю.
Вопрос в другом, как правильно собрать и разобрать последовательность

def x=1;
def y=1;


это список. Как его разбрать в отдельные строчки и как потом эти строчки правильно объединить.
Re[5]: не пойму проблемы
От: CodingUnit Россия  
Дата: 23.08.13 16:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Это я знаю.

А>Вопрос в другом, как правильно собрать и разобрать последовательность

А>
А>def x=1;
А>def y=1;
А>


А>это список. Как его разбрать в отдельные строчки и как потом эти строчки правильно объединить.


Странная задача в языке, который может работать с выражениями, обьясните более полную задачу что вы хотите сделать, пока смутно представляется работа со строками. Эту работу обычно выполняет лексер и парсер, лексер выделяет токены, ключевые слова, операторы, парсер преобразует их в дерево выражений, так обычно идет работа с текстовыми языками. Если вы хотите делать задачу лексера самому то вам надо научится выделять токены, обходить строку, исключая пробелы и другие разделители. Если работать со строками многострочный текст можно разделить функциями Split() с набором разделителей и Join из класса string



def str = ["def x = 1;", "def y = 1;"]; // список строк
foreach (elem in str)
{
  def elems = elem.Split(array[" "], StringSplitOptions.RemoveEmptyEntries); // получаете список строк ["def", "x", "=", "1"]
  
  def join = string.Join(" ", str); // соединяет элементы обратно через пробелы

}


если я правильно понял что вы хотите, но вообще все это как то странно выглядит, нужно знать задачу.
Re[6]: не пойму проблемы
От: Аноним  
Дата: 23.08.13 16:45
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Здравствуйте, Аноним, Вы писали:


А>>Это я знаю.

А>>Вопрос в другом, как правильно собрать и разобрать последовательность

А>>
А>>def x=1;
А>>def y=1;
А>>


А>>это список. Как его разбрать в отдельные строчки и как потом эти строчки правильно объединить.


CU>Странная задача в языке, который может работать с выражениями, обьясните более полную задачу что вы хотите сделать, пока смутно представляется работа со строками. Эту работу обычно выполняет лексер и парсер, лексер выделяет токены, ключевые слова, операторы, парсер преобразует их в дерево выражений, так обычно идет работа с текстовыми языками. Если вы хотите делать задачу лексера самому то вам надо научится выделять токены, обходить строку, исключая пробелы и другие разделители. Если работать со строками многострочный текст можно разделить функциями Split() с набором разделителей и Join из класса string



CU>

CU>def str = ["def x = 1;", "def y = 1;"]; // список строк
CU>foreach (elem in str)
CU>{
CU>  def elems = elem.Split(array[" "], StringSplitOptions.RemoveEmptyEntries); // получаете список строк ["def", "x", "=", "1"]
  
CU>  def join = string.Join(" ", str); // соединяет элементы обратно через пробелы

CU>}
CU>


CU>если я правильно понял что вы хотите, но вообще все это как то странно выглядит, нужно знать задачу.


Хочу сделать макрос упрощения выражений.

def x=1;
def y= 88+x;
y


в результате

89

наиболее примитивный вариант
Re[7]: не пойму проблемы
От: CodingUnit Россия  
Дата: 23.08.13 17:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Хочу сделать макрос упрощения выражений.


А>def x=1;

А>def y= 88+x;
А>y


А>в результате


А>89


А>наиболее примитивный вариант


Ну теперь хоть яснее, вообще это сложный макрос, для таких целей используют разные решатели, анализаторы CFG (Control Flow Graph), интерпретаторы, не знаю что вам посоветовать чтобы решить задачу, но в примитиве все это делается тем же match оператором, только над группой выражений, только вам надо что то делать с промежуточным состоянием, после разбора одного выражения решить что получилось и как его комбинировать с другим. Может здесь строить дерево выражений из списка преобразовать в некое промежуточное древо, которое было бы проще анализировать. Такую работу проводит компилятор Н в своих глубинах, когда определяется переменная в хэше имен переменных заводится имя переменной и значение, все это потом муторно обрабатывается для поиска ошибок.

Вообще все это делается обычными функциями над списками, Fold, Map.

FoldLeft обходит список и накапливает результат в аккумуляторе и получает одно значение. Map преобразует список в другой список,

например можно так:
здесь я дерево выражений преобразую в другое дерево ближе к предметной области, потом это дерево анализируется или преобразуется в что то другое или конечный результат


variant VariableType
{
  | Constant { val : int; }
  | Variable { name : string;}
}

variant OperatorExpression
{
 | Sum { left : VariableType; right : VariableType}
 | Other { expr : PExpr; } 
}

variant AnalyseTree
{
 | VarCreate { name : string; value : Literal; }
 | DefExpression { name : string; value : OperatorExpression; }

}

macro analyze(expr)
{

// анализируем операторы выражений
def analyse_operator(n)
{
 // смотрим сложение константы с переменной
 | <[ $(x : int) + $(y : usesite) ]> => OperatorExpression.Sum(VariableType.Constant(x), VariableType.Variable(y))
  // в другом порядке
 | <[ $(x : usesite) + $(y : int) ]> => OperatorExpression.Sum(VariableType.Variable(x), VariableType.Constant(y))
 | _                                 => OperatorExpression.Other(n)
}

def map(expr)
{
  // смотрим является ли это def определение
  | <[ def $x = $v]> =>  // можно зарегистрировать переменную с именем x и значением v, x и v тоже надо матчить чтобы докопаться до имен и их содержимого здесь можно выдать новый член дерева
                        match (v)
                        {
                          // если это обычная константа
                          | <[ $(n : int) ]> as e => AnalyseTree.VarCreate(x.ToString(), e.val) // создаем новое дерево с уже полученными значениями из выражений Н
                          | _                     => AnalyseTree.DefExpression(x.ToString(), analyse_operator(v)) // сразу анализируем операторы для их последующей обработки
                        }
}

def new_expr = match (expr)
{
 | <[ ..$seq ]> => seq.Map(map) // обходим с получением из списка выражений свое дерево
}
// обходим без результата но сохраняем в некоем промежуточном состоянии результаты обхода
 foreach (expr in new_expr)
 {
   | AnalyseTree.VarCreate(n, val) => hashtable[n] = val // регистрация переменной со значением
   | _ => ()..// 
 }

def eval(expr)
{
 | OperatorExpression.Sum(VariableType.Name(l), VariableType.Constant(r)) => def val = hashtable[l]; // получаем значение переменной зарегестрированной в хэштаблице
                                                                             val + r // выдаем значение
 | _ => ..// обработка других операторов
}

def fold_expr(expr, acc)
{
  match (expr)
  {
   | DefExpression(n, v) => eval(v)
   | _                   => acc
  }
}
 
def result = new_expr.FoldLeft(0, fold_expr); // получаем результат преобразования 
}



все это можно делать многократно и по разным принципам, исследуя выражение и дерево, порождая новые деревья через Map, накапливая результат в функциональном стиле через Fold либо сохраняя в промежуточном состоянии, где то в картах, массивах и переменных. Также можно обходить полное дерево выражения с помощью функций Macros.TraverseExpr и Macros.TraverseExprWithContext в сборке компилятора, там надо задавать несколько параметров, все сводится к полному обхода дерева выражения PExpr с его анализом и преобразовании в новый PExpr, можно сохранять результат где то в промежуточном состоянии. Полный вопрос анализа выражений для их упрощения выходит за рамки ответа, это отдельная область.
Re[8]: не пойму проблемы
От: Аноним  
Дата: 23.08.13 17:57
Оценка:
Здравствуйте, CodingUnit, Вы писали:

Более простой вопрос


using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;

namespace SC
{
  public macro razbor(y)
  {
    
    def id(x){x}   
      
    match (y){
        | <[ ..$seq ]> => seq.Map(id);
        | <[  ]> => <[ ]>;
  }
}
}




using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Console;
using System.Linq;
using SC;

module Program
{
  Main() : void
  {
      
      
     SC.razbor(
    {
        def x1=1;
        def y =  2;
    
    }
    ) ;
      
    WriteLine("Hi!");
    _ = ReadLine();
  }
}


ошибка
error : List of expression parameters outside of quoted sequence: use <[ { .. $x } ]> pattern
confused by earlier errors bailing out
не пойму как с ней бороться....

остальное понятнее, чем эта ошибка
добавление фигурных скобок не помогает
error : Cannot implicitly convert type 'list[Nemerle.Compiler.Parsetree.PExpr-]' to 'Nemerle.Compiler.Parsetree.PExpr'.

где засада не могу понять
Re[9]: не пойму проблемы
От: CodingUnit Россия  
Дата: 23.08.13 18:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, CodingUnit, Вы писали:


А>Более простой вопрос



public macro razbor(y)
  {

    def id(x) { x }

    match (y)
    {
      | <[ {..$seq} ]> => def exprs = seq.Map(id);
                          <[ {..$exprs} ]> // соединение списка выражений в одно выражение
      | <[  ]> => <[ ]>;
    }
  }


//
razbor({
def x = 1;
def y = 2;
});


[nemerle]


А>где засада не могу понять


Так должно работать, в сообщении написано, для матча списка часто нужно писать {..$seq} скобки потому как ..$ оператор в квазицитатах умеет работать только внутри скобок, тоже и для соединения выражений.
Re[5]: не пойму проблемы
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.08.13 19:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Вопрос в другом, как правильно собрать и разобрать последовательность


А>
А>def x=1;
А>def y=1;
А>


А>это список. Как его разбрать в отдельные строчки и как потом эти строчки правильно объединить.


1. Чтобы передать макросу сразу несколько выражений их нужно поместить в блок%
{
  def x = 1;
  def y = 1;
}


2. Чтобы разобрать их нужно написать:
match (expr)
{
  | <[ { ..$exprs } ]> => Делаем что-то с exprs в котором лежат подвыражения.
  | _ => обрабатываем ошибку
}


3. Чтобы собрать выражения обратно в блок, нужно воспользоваться той же цитатой:
def e = <[ { ..$exprs } ]>;
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: не пойму проблемы
От: VladD2 Российская Империя www.nemerle.org
Дата: 23.08.13 19:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Хочу сделать макрос упрощения выражений.


А>def x=1;

А>def y= 88+x;
А>y
А>в результате
А>89

Тут единственная сложность будет со связыванием имен. Ведь переменной может и не быть или она может быть объявлена неизвестно где.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.